You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by em...@apache.org on 2017/10/20 19:01:32 UTC
[07/10] incubator-ariatosca git commit: ARIA-1 Parser test suite
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/data_types.py
index 216f1e4..b85caa1 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/data_types.py
@@ -37,13 +37,13 @@ class Timezone(tzinfo):
super(Timezone, self).__init__()
self._offset = timedelta(hours=hours, minutes=minutes)
- def utcoffset(self, dt): # pylint: disable=unused-argument
+ def utcoffset(self, dt): # pylint: disable=unused-argument
return self._offset
- def tzname(self, dt): # pylint: disable=unused-argument
- return str(self._offset)
+ def tzname(self, dt): # pylint: disable=unused-argument
+ return unicode(self._offset)
- def dst(self, dt): # pylint: disable=unused-argument
+ def dst(self, dt): # pylint: disable=unused-argument
return Timezone._ZERO
_ZERO = timedelta(0)
@@ -74,8 +74,8 @@ class Timestamp(object):
r'(([ \t]*)Z|(?P<tzhour>[-+][0-9][0-9])?(:(?P<tzminute>[0-9][0-9])?)?)?$'
CANONICAL = '%Y-%m-%dT%H:%M:%S'
- def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
- value = str(value)
+ def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ value = unicode(value)
match = re.match(Timestamp.REGULAR_SHORT, value)
if match is not None:
# Parse short form
@@ -116,8 +116,8 @@ class Timestamp(object):
Timezone(tzhour, tzminute))
else:
raise ValueError(
- 'timestamp must be formatted as YAML ISO8601 variant or "YYYY-MM-DD": %s'
- % safe_repr(value))
+ u'timestamp must be formatted as YAML ISO8601 variant or "YYYY-MM-DD": {0}'
+ .format(safe_repr(value)))
@property
def as_datetime_utc(self):
@@ -129,8 +129,8 @@ class Timestamp(object):
def __str__(self):
the_datetime = self.as_datetime_utc
- return '%s%sZ' \
- % (the_datetime.strftime(Timestamp.CANONICAL), Timestamp._fraction_as_str(the_datetime))
+ return u'{0}{1}Z'.format(the_datetime.strftime(Timestamp.CANONICAL),
+ Timestamp._fraction_as_str(the_datetime))
def __repr__(self):
return repr(self.__str__())
@@ -145,7 +145,7 @@ class Timestamp(object):
@staticmethod
def _fraction_as_str(the_datetime):
- return '{0:g}'.format(the_datetime.microsecond / 1000000.0).lstrip('0')
+ return u'{0:g}'.format(the_datetime.microsecond / 1000000.0).lstrip('0')
@total_ordering
@@ -165,7 +165,7 @@ class Version(object):
REGEX = \
r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<fix>\d+)' + \
- r'((\.(?P<qualifier>\d+))(\-(?P<build>\d+))?)?)?$'
+ r'((\.(?P<qualifier>\w+))(\-(?P<build>\d+))?)?)?$'
@staticmethod
def key(version):
@@ -174,14 +174,13 @@ class Version(object):
"""
return (version.major, version.minor, version.fix, version.qualifier, version.build)
- def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
- str_value = str(value)
- match = re.match(Version.REGEX, str_value)
+ def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ str_value = unicode(value)
+ match = re.match(Version.REGEX, str_value, flags=re.UNICODE)
if match is None:
raise ValueError(
- 'version must be formatted as <major_version>.<minor_version>'
- '[.<fix_version>[.<qualifier>[-<build_version]]]: %s'
- % safe_repr(value))
+ u'version must be formatted as <major_version>.<minor_version>'
+ u'[.<fix_version>[.<qualifier>[-<build_version]]]: {0}'.format(safe_repr(value)))
self.value = str_value
@@ -193,8 +192,6 @@ class Version(object):
if self.fix is not None:
self.fix = int(self.fix)
self.qualifier = match.group('qualifier')
- if self.qualifier is not None:
- self.qualifier = int(self.qualifier)
self.build = match.group('build')
if self.build is not None:
self.build = int(self.build)
@@ -215,6 +212,7 @@ class Version(object):
return (self.major, self.minor, self.fix, self.qualifier, self.build) == \
(version.major, version.minor, version.fix, version.qualifier, version.build)
+ @implements_specification('3.2.2.1', 'tosca-simple-1.0')
def __lt__(self, version):
if self.major < version.major:
return True
@@ -225,9 +223,7 @@ class Version(object):
if self.fix < version.fix:
return True
elif self.fix == version.fix:
- if self.qualifier < version.qualifier:
- return True
- elif self.qualifier == version.qualifier:
+ if self.qualifier == version.qualifier:
if self.build < version.build:
return True
return False
@@ -244,28 +240,29 @@ class Range(object):
#TYPE_TOSCA_RANGE>`__
"""
- def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
if not isinstance(value, list):
- raise ValueError('range value is not a list: %s' % safe_repr(value))
+ raise ValueError(u'range value is not a list: {0}'.format(safe_repr(value)))
if len(value) != 2:
- raise ValueError('range value does not have exactly 2 elements: %s' % safe_repr(value))
+ raise ValueError(u'range value does not have exactly 2 elements: {0}'
+ .format(safe_repr(value)))
def is_int(v):
return isinstance(v, int) and (not isinstance(v, bool)) # In Python bool is an int
if not is_int(value[0]):
- raise ValueError('lower bound of range is not a valid integer: %s'
- % safe_repr(value[0]))
+ raise ValueError(u'lower bound of range is not a valid integer: {0}'
+ .format(safe_repr(value[0])))
if value[1] != 'UNBOUNDED':
if not is_int(value[1]):
- raise ValueError('upper bound of range is not a valid integer or "UNBOUNDED": %s'
- % safe_repr(value[0]))
+ raise ValueError(u'upper bound of range is not a valid integer or "UNBOUNDED": {0}'
+ .format(safe_repr(value[0])))
if value[0] >= value[1]:
raise ValueError(
- 'upper bound of range is not greater than the lower bound: %s >= %s'
- % (safe_repr(value[0]), safe_repr(value[1])))
+ u'upper bound of range is not greater than the lower bound: {0} >= {1}'
+ .format(safe_repr(value[0]), safe_repr(value[1])))
self.value = value
@@ -294,9 +291,9 @@ class List(list):
"""
@staticmethod
- def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
if not isinstance(value, list):
- raise ValueError('"list" data type value is not a list: %s' % safe_repr(value))
+ raise ValueError(u'"list" data type value is not a list: {0}'.format(safe_repr(value)))
entry_schema_type = entry_schema._get_type(context)
entry_schema_constraints = entry_schema.constraints
@@ -328,12 +325,12 @@ class Map(StrictDict):
"""
@staticmethod
- def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
if not isinstance(value, dict):
- raise ValueError('"map" data type value is not a dict: %s' % safe_repr(value))
+ raise ValueError(u'"map" data type value is not a dict: {0}'.format(safe_repr(value)))
if entry_schema is None:
- raise ValueError('"map" data type does not define "entry_schema"')
+ raise ValueError(u'"map" data type does not define "entry_schema"')
entry_schema_type = entry_schema._get_type(context)
entry_schema_constraints = entry_schema.constraints
@@ -348,7 +345,7 @@ class Map(StrictDict):
return the_map
def __init__(self, items=None):
- super(Map, self).__init__(items, key_class=str)
+ super(Map, self).__init__(items, key_class=basestring)
# Can't define as property because it's old-style Python class
def as_raw(self):
@@ -374,29 +371,31 @@ class Scalar(object):
"""
return scalar.value
- def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
- str_value = str(value)
- match = re.match(self.REGEX, str_value) # pylint: disable=no-member
+ def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+ str_value = unicode(value)
+ match = re.match(self.REGEX, str_value, flags=re.UNICODE) # pylint: disable=no-member
if match is None:
- raise ValueError('scalar must be formatted as <scalar> <unit>: %s' % safe_repr(value))
+ raise ValueError(u'scalar must be formatted as <scalar> <unit>: {0}'
+ .format(safe_repr(value)))
self.factor = float(match.group('scalar'))
if self.factor < 0:
- raise ValueError('scalar is negative: %s' % safe_repr(self.factor))
+ raise ValueError('scalar is negative: {0}'.format(safe_repr(self.factor)))
self.unit = match.group('unit')
unit_lower = self.unit.lower()
unit_size = None
- for k, v in self.UNITS.iteritems(): # pylint: disable=no-member
+ for k, v in self.UNITS.iteritems(): # pylint: disable=no-member
if k.lower() == unit_lower:
self.unit = k
unit_size = v
break
if unit_size is None:
- raise ValueError('scalar specified with unsupported unit: %s' % safe_repr(self.unit))
+ raise ValueError(u'scalar specified with unsupported unit: {0}'
+ .format(safe_repr(self.unit)))
- self.value = self.TYPE(self.factor * unit_size) # pylint: disable=no-member
+ self.value = self.TYPE(self.factor * unit_size) # pylint: disable=no-member
@property
def as_raw(self):
@@ -404,10 +403,10 @@ class Scalar(object):
('value', self.value),
('factor', self.factor),
('unit', self.unit),
- ('unit_size', self.UNITS[self.unit]))) # pylint: disable=no-member
+ ('unit_size', self.UNITS[self.unit]))) # pylint: disable=no-member
def __str__(self):
- return '%s %s' % (self.value, self.UNIT) # pylint: disable=no-member
+ return u'{0} {1}'.format(self.value, self.UNIT) # pylint: disable=no-member
def __repr__(self):
return repr(self.__str__())
@@ -416,14 +415,14 @@ class Scalar(object):
if isinstance(scalar, Scalar):
value = scalar.value
else:
- value = self.TYPE(scalar) # pylint: disable=no-member
+ value = self.TYPE(scalar) # pylint: disable=no-member
return self.value == value
def __lt__(self, scalar):
if isinstance(scalar, Scalar):
value = scalar.value
else:
- value = self.TYPE(scalar) # pylint: disable=no-member
+ value = self.TYPE(scalar) # pylint: disable=no-member
return self.value < value
@@ -509,12 +508,12 @@ class ScalarFrequency(Scalar):
# The following are hooked in the YAML as 'coerce_value' extensions
#
-def coerce_timestamp(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+def coerce_timestamp(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
return coerce_to_data_type_class(context, presentation, Timestamp, entry_schema, constraints,
value, aspect)
-def coerce_version(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+def coerce_version(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
return coerce_to_data_type_class(context, presentation, Version, entry_schema, constraints,
value, aspect)
@@ -533,23 +532,23 @@ def coerce_range(context, presentation, the_type, entry_schema, constraints, val
value, aspect)
-def coerce_list(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+def coerce_list(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
return coerce_to_data_type_class(context, presentation, List, entry_schema, constraints,
value, aspect)
-def coerce_map_value(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
+def coerce_map_value(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
return coerce_to_data_type_class(context, presentation, Map, entry_schema, constraints, value,
aspect)
-def coerce_scalar_unit_size(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument
+def coerce_scalar_unit_size(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument
aspect):
return coerce_to_data_type_class(context, presentation, ScalarSize, entry_schema, constraints,
value, aspect)
-def coerce_scalar_unit_time(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument
+def coerce_scalar_unit_time(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument
aspect):
return coerce_to_data_type_class(context, presentation, ScalarTime, entry_schema, constraints,
value, aspect)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/definitions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/definitions.py b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
index 9158776..02794e8 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/definitions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
@@ -15,7 +15,9 @@
from aria.utils.collections import FrozenDict
from aria.utils.caching import cachedmethod
+from aria.utils.formatting import safe_repr
from aria.parser import implements_specification
+from aria.parser.validation import Issue
from aria.parser.presentation import (has_fields, short_form_field, allow_unknown_fields,
primitive_field, primitive_list_field, object_field,
object_list_field, object_dict_field,
@@ -192,8 +194,8 @@ class AttributeDefinition(ExtensiblePresentation):
@has_fields
-@implements_specification('3.5.12', 'tosca-simple-1.0')
-class ParameterDefinition(PropertyDefinition):
+@implements_specification('3.5.12-1', 'tosca-simple-1.0')
+class InputDefinition(PropertyDefinition):
"""
A parameter definition is essentially a TOSCA property definition; however, it also allows a
value to be assigned to it (as for a TOSCA property assignment). In addition, in the case of
@@ -205,6 +207,18 @@ class ParameterDefinition(PropertyDefinition):
#DEFN_ELEMENT_PARAMETER_DEF>`__
"""
+ @field_validator(data_value_validator)
+ @primitive_field()
+ def value(self):
+ """
+ The type-compatible value to assign to the named parameter. Parameter values may be provided
+ as the result from the evaluation of an expression or a function.
+ """
+
+
+@has_fields
+@implements_specification('3.5.12-2', 'tosca-simple-1.0')
+class OutputDefinition(InputDefinition):
@field_validator(data_type_validator())
@primitive_field(str)
def type(self):
@@ -214,15 +228,10 @@ class ParameterDefinition(PropertyDefinition):
Note: This keyname is required for a TOSCA Property definition, but is not for a TOSCA
Parameter definition.
- :type: :obj:`basestring`
- """
+ ARIA NOTE: the spec must be mistaken: inputs should have this field requires, only outputs
+ have it as optional.
- @field_validator(data_value_validator)
- @primitive_field()
- def value(self):
- """
- The type-compatible value to assign to the named parameter. Parameter values may be provided
- as the result from the evaluation of an expression or a function.
+ :type: :obj:`basestring`
"""
@@ -283,7 +292,7 @@ class InterfaceDefinition(ExtensiblePresentation):
@field_validator(type_validator('interface type', convert_name_to_full_type_name,
'interface_types'))
- @primitive_field(str)
+ @primitive_field(str, required=True)
def type(self):
"""
ARIA NOTE: This field is not mentioned in the spec, but is implied.
@@ -323,7 +332,7 @@ class InterfaceDefinition(ExtensiblePresentation):
def _validate(self, context):
super(InterfaceDefinition, self)._validate(context)
if self.operations:
- for operation in self.operations.itervalues(): # pylint: disable=no-member
+ for operation in self.operations.itervalues(): # pylint: disable=no-member
operation._validate(context)
@@ -342,6 +351,8 @@ class RelationshipDefinition(ExtensiblePresentation):
The optional reserved keyname used to provide the name of the Relationship Type for the
requirement definition's relationship keyname.
+ ARIA NOTE: the spec shows this as a required field.
+
:type: :obj:`basestring`
"""
@@ -428,6 +439,16 @@ class RequirementDefinition(ExtensiblePresentation):
def _get_node_type(self, context):
return context.presentation.get_from_dict('service_template', 'node_types', self.node)
+ def _validate(self, context):
+ super(RequirementDefinition, self)._validate(context)
+ occurrences = self.occurrences
+ if (occurrences is not None) and ((occurrences.value[0] < 0) or \
+ ((occurrences.value[1] != 'UNBOUNDED') and (occurrences.value[1] < 0))):
+ context.validation.report(
+ 'requirements definition "{0}" occurrences range includes negative integers: {1}'
+ .format(self._name, safe_repr(occurrences)),
+ locator=self._locator, level=Issue.BETWEEN_TYPES)
+
@short_form_field('type')
@has_fields
@@ -516,3 +537,13 @@ class CapabilityDefinition(ExtensiblePresentation):
if container_parent is not None else None
return container_parent_capabilities.get(self._name) \
if container_parent_capabilities is not None else None
+
+ def _validate(self, context):
+ super(CapabilityDefinition, self)._validate(context)
+ occurrences = self.occurrences
+ if (occurrences is not None) and ((occurrences.value[0] < 0) or \
+ ((occurrences.value[1] != 'UNBOUNDED') and (occurrences.value[1] < 0))):
+ context.validation.report(
+ 'capability definition "{0}" occurrences range includes negative integers: {1}'
+ .format(self._name, safe_repr(occurrences)),
+ locator=self._locator, level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/misc.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/misc.py b/extensions/aria_extension_tosca/simple_v1_0/misc.py
index 221163c..914691e 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/misc.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py
@@ -20,14 +20,16 @@ from aria.parser import implements_specification
from aria.parser.presentation import (AsIsPresentation, has_fields, allow_unknown_fields,
short_form_field, primitive_field, primitive_list_field,
primitive_dict_unknown_fields, object_field,
- object_list_field, object_dict_field, field_validator,
- type_validator)
+ object_list_field, object_dict_field, field_getter,
+ field_validator, type_validator, not_negative_validator)
+from .data_types import Version
from .modeling.data_types import (get_data_type, get_data_type_value, get_property_constraints,
apply_constraint_to_value)
from .modeling.substitution_mappings import (validate_substitution_mappings_requirement,
validate_substitution_mappings_capability)
from .presentation.extensible import ExtensiblePresentation
+from .presentation.field_getters import data_type_class_getter
from .presentation.field_validators import (constraint_clause_field_validator,
constraint_clause_in_range_validator,
constraint_clause_valid_values_validator,
@@ -47,7 +49,7 @@ class Description(AsIsPresentation):
#DEFN_ELEMENT_DESCRIPTION>`__
"""
- def __init__(self, name=None, raw=None, container=None, cls=None): # pylint: disable=unused-argument
+ def __init__(self, name=None, raw=None, container=None, cls=None): # pylint: disable=unused-argument
super(Description, self).__init__(name, raw, container, cls=unicode)
def _dump(self, context):
@@ -79,6 +81,7 @@ class MetaData(ExtensiblePresentation):
as a single-line string value.
"""
+ @field_getter(data_type_class_getter(Version, allow_null=True))
@primitive_field(str)
@implements_specification('3.9.3.5', 'tosca-simple-1.0')
def template_version(self):
@@ -87,7 +90,7 @@ class MetaData(ExtensiblePresentation):
service template as a single-line string value.
"""
- @primitive_dict_unknown_fields()
+ @primitive_dict_unknown_fields(str)
def custom(self):
"""
:type: dict
@@ -135,6 +138,10 @@ class Repository(ExtensiblePresentation):
def _get_credential(self, context):
return get_data_type_value(context, self, 'credential', 'tosca.datatypes.Credential')
+ def _validate(self, context):
+ super(Repository, self)._validate(context)
+ self._get_credential(context)
+
@short_form_field('file')
@has_fields
@@ -255,18 +262,21 @@ class ConstraintClause(ExtensiblePresentation):
Constrains a property or parameter to a value that is in the list of declared values.
"""
+ @field_validator(not_negative_validator)
@primitive_field(int)
def length(self):
"""
Constrains the property or parameter to a value of a given length.
"""
+ @field_validator(not_negative_validator)
@primitive_field(int)
def min_length(self):
"""
Constrains the property or parameter to a value to a minimum length.
"""
+ @field_validator(not_negative_validator)
@primitive_field(int)
def max_length(self):
"""
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index d960e05..da326fa 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -29,7 +29,7 @@ from datetime import datetime
from ruamel import yaml
from aria.parser.validation import Issue
-from aria.utils.formatting import string_list_as_string
+from aria.utils.formatting import (string_list_as_string, safe_repr)
from aria.utils.collections import (StrictDict, OrderedDict)
from aria.orchestrator import WORKFLOW_DECORATOR_RESERVED_ARGUMENTS
from aria.modeling.models import (Type, ServiceTemplate, NodeTemplate,
@@ -50,7 +50,7 @@ from ..data_types import coerce_value
IMPLEMENTATION_PREFIX_REGEX = re.compile(r'(?<!\\)(?:\\\\)*>')
-def create_service_template_model(context): # pylint: disable=too-many-locals,too-many-branches
+def create_service_template_model(context): # pylint: disable=too-many-locals,too-many-branches
model = ServiceTemplate(created_at=datetime.now(),
main_file_name=os.path.basename(str(context.presentation.location)))
@@ -316,6 +316,10 @@ def create_relationship_template_model(context, service_template, relationship):
create_parameter_models_from_assignments(model.properties,
relationship.properties,
model_cls=Property)
+ # TODO: does not exist in models, but should
+ #create_parameter_models_from_assignments(model.attributes,
+ # relationship.attributes,
+ # model_cls=Attribute)
create_interface_template_models(context, service_template, model.interface_templates,
relationship.interfaces)
@@ -347,6 +351,10 @@ def create_capability_template_model(context, service_template, capability):
create_parameter_models_from_assignments(model.properties,
capability.properties,
model_cls=Property)
+ # TODO: does not exist in models, but should
+ #create_parameter_models_from_assignments(model.attributes,
+ # capability.attributes,
+ # model_cls=Attribute)
return model
@@ -400,7 +408,7 @@ def create_operation_template_model(context, service_template, operation):
value = yaml.load(value)
except yaml.parser.MarkedYAMLError as e:
context.validation.report(
- 'YAML parser {0} in operation configuration: {1}'
+ u'YAML parser {0} in operation configuration: {1}'
.format(e.problem, value),
locator=implementation._locator,
level=Issue.FIELD)
@@ -519,7 +527,7 @@ def create_workflow_operation_template_model(context, service_template, policy):
used_reserved_names = WORKFLOW_DECORATOR_RESERVED_ARGUMENTS.intersection(model.inputs.keys())
if used_reserved_names:
- context.validation.report('using reserved arguments in workflow policy "{0}": {1}'
+ context.validation.report(u'using reserved arguments in workflow policy "{0}": {1}'
.format(
policy._name,
string_list_as_string(used_reserved_names)),
@@ -631,7 +639,8 @@ def create_node_filter_constraints(context, node_filter, target_node_template_co
for property_name, constraint_clause in properties:
constraint = create_constraint(context, node_filter, constraint_clause, property_name,
None)
- target_node_template_constraints.append(constraint)
+ if constraint is not None:
+ target_node_template_constraints.append(constraint)
capabilities = node_filter.capabilities
if capabilities is not None:
@@ -641,24 +650,33 @@ def create_node_filter_constraints(context, node_filter, target_node_template_co
for property_name, constraint_clause in properties:
constraint = create_constraint(context, node_filter, constraint_clause,
property_name, capability_name)
- target_node_template_constraints.append(constraint)
+ if constraint is not None:
+ target_node_template_constraints.append(constraint)
-def create_constraint(context, node_filter, constraint_clause, property_name, capability_name): # pylint: disable=too-many-return-statements
+def create_constraint(context, node_filter, constraint_clause, property_name, capability_name): # pylint: disable=too-many-return-statements
+ if (not isinstance(constraint_clause._raw, dict)) or (len(constraint_clause._raw) != 1):
+ context.validation.report(
+ u'node_filter constraint is not a dict with one key: {0}'
+ .format(safe_repr(constraint_clause._raw)),
+ locator=node_filter._locator,
+ level=Issue.FIELD)
+ return None
+
constraint_key = constraint_clause._raw.keys()[0]
the_type = constraint_clause._get_type(context)
- def coerce_constraint(constraint):
+ def coerce_constraint(constraint, the_type=the_type):
if the_type is not None:
return coerce_value(context, node_filter, the_type, None, None, constraint,
constraint_key)
else:
return constraint
- def coerce_constraints(constraints):
+ def coerce_constraints(constraints, the_type=the_type):
if the_type is not None:
- return tuple(coerce_constraint(constraint) for constraint in constraints)
+ return tuple(coerce_constraint(constraint, the_type) for constraint in constraints)
else:
return constraints
@@ -685,18 +703,22 @@ def create_constraint(context, node_filter, constraint_clause, property_name, ca
coerce_constraints(constraint_clause.valid_values))
elif constraint_key == 'length':
return Length(property_name, capability_name,
- coerce_constraint(constraint_clause.length))
+ coerce_constraint(constraint_clause.length, int))
elif constraint_key == 'min_length':
return MinLength(property_name, capability_name,
- coerce_constraint(constraint_clause.min_length))
+ coerce_constraint(constraint_clause.min_length, int))
elif constraint_key == 'max_length':
return MaxLength(property_name, capability_name,
- coerce_constraint(constraint_clause.max_length))
+ coerce_constraint(constraint_clause.max_length, int))
elif constraint_key == 'pattern':
return Pattern(property_name, capability_name,
- coerce_constraint(constraint_clause.pattern))
+ coerce_constraint(constraint_clause.pattern, unicode))
else:
- raise ValueError('malformed node_filter: {0}'.format(constraint_key))
+ context.validation.report(
+ u'unsupported node_filter constraint: {0}'.format(constraint_key),
+ locator=node_filter._locator,
+ level=Issue.FIELD)
+ return None
def split_prefix(string):
@@ -704,7 +726,7 @@ def split_prefix(string):
Splits the prefix on the first non-escaped ">".
"""
- split = IMPLEMENTATION_PREFIX_REGEX.split(string, 1)
+ split = IMPLEMENTATION_PREFIX_REGEX.split(string, 1) if string is not None else ()
if len(split) < 2:
return None, None
return split[0].strip(), split[1].strip()
@@ -741,7 +763,7 @@ def extract_implementation_primary(context, service_template, presentation, mode
model.function = postfix
if model.plugin_specification is None:
context.validation.report(
- 'no policy for plugin "{0}" specified in operation implementation: {1}'
+ u'no policy for plugin "{0}" specified in operation implementation: {1}'
.format(prefix, primary),
locator=presentation._get_child_locator('properties', 'implementation'),
level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
index 1b95bec..ca32dde 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
@@ -73,8 +73,8 @@ def get_inherited_capability_definitions(context, presentation, for_presentation
if not type1._is_descendant(context, type2):
context.validation.report(
- 'capability definition type "{0}" is not a descendant of overridden '
- 'capability definition type "{1}"' \
+ u'capability definition type "{0}" is not a descendant of overridden '
+ u'capability definition type "{1}"' \
.format(type1._name, type2._name),
locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES)
@@ -141,7 +141,7 @@ def get_template_capabilities(context, presentation):
capability_assignment._reset_method_cache()
else:
context.validation.report(
- 'capability "{0}" not declared at node type "{1}" in "{2}"'
+ u'capability "{0}" not declared at node type "{1}" in "{2}"'
.format(capability_name, presentation.type, presentation._fullname),
locator=our_capability_assignment._locator, level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
index bd9037f..b3c2e49 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
@@ -23,7 +23,7 @@ def get_default_raw_from_copy(presentation, field_name):
"""
copy = presentation._raw.get('copy')
- if copy is not None:
+ if isinstance(copy, basestring):
templates = getattr(presentation._container, field_name)
if templates is not None:
template = templates.get(copy)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
index 13ce9a3..25e53c6 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
@@ -52,7 +52,7 @@ def get_inherited_constraints(context, presentation):
return constraints
-def coerce_data_type_value(context, presentation, data_type, entry_schema, constraints, value, # pylint: disable=unused-argument
+def coerce_data_type_value(context, presentation, data_type, entry_schema, constraints, value, # pylint: disable=unused-argument
aspect):
"""
Handles the ``_coerce_data()`` hook for complex data types.
@@ -90,8 +90,8 @@ def coerce_data_type_value(context, presentation, data_type, entry_schema, const
aspect)
else:
context.validation.report(
- 'assignment to undefined property "%s" in type "%s" in "%s"'
- % (name, data_type._fullname, presentation._fullname),
+ u'assignment to undefined property "{0}" in type "{1}" in "{2}"'
+ .format(name, data_type._fullname, presentation._fullname),
locator=get_locator(v, value, presentation), level=Issue.BETWEEN_TYPES)
# Fill in defaults from the definitions, and check if required definitions have not been
@@ -108,15 +108,15 @@ def coerce_data_type_value(context, presentation, data_type, entry_schema, const
if getattr(definition, 'required', False) and (temp.get(name) is None):
context.validation.report(
- 'required property "%s" in type "%s" is not assigned a value in "%s"'
- % (name, data_type._fullname, presentation._fullname),
+ u'required property "{0}" in type "{1}" is not assigned a value in "{2}"'
+ .format(name, data_type._fullname, presentation._fullname),
locator=presentation._get_child_locator('definitions'),
level=Issue.BETWEEN_TYPES)
value = temp
elif value is not None:
- context.validation.report('value of type "%s" is not a dict in "%s"'
- % (data_type._fullname, presentation._fullname),
+ context.validation.report(u'value of type "{0}" is not a dict in "{1}"'
+ .format(data_type._fullname, presentation._fullname),
locator=get_locator(value, presentation),
level=Issue.BETWEEN_TYPES)
value = None
@@ -131,8 +131,8 @@ def validate_data_type_name(context, presentation):
name = presentation._name
if get_primitive_data_type(name) is not None:
- context.validation.report('data type name is that of a built-in type: %s'
- % safe_repr(name),
+ context.validation.report(u'data type name is that of a built-in type: {0}'
+ .format(safe_repr(name)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
@@ -201,7 +201,7 @@ def get_property_constraints(context, presentation):
# ConstraintClause
#
-def apply_constraint_to_value(context, presentation, constraint_clause, value): # pylint: disable=too-many-statements,too-many-return-statements,too-many-branches
+def apply_constraint_to_value(context, presentation, constraint_clause, value): # pylint: disable=too-many-statements,too-many-return-statements,too-many-branches
"""
Returns false if the value does not conform to the constraint.
"""
@@ -216,10 +216,10 @@ def apply_constraint_to_value(context, presentation, constraint_clause, value):
constraint_key)
def report(message, constraint):
- context.validation.report('value %s %s per constraint in "%s": %s'
- % (message, safe_repr(constraint),
- presentation._name or presentation._container._name,
- safe_repr(value)),
+ context.validation.report(u'value {0} {1} per constraint in "{2}": {3}'
+ .format(message, safe_repr(constraint),
+ presentation._name or presentation._container._name,
+ safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_FIELDS)
if constraint_key == 'equal':
@@ -318,15 +318,15 @@ def apply_constraint_to_value(context, presentation, constraint_clause, value):
#
def get_data_type_value(context, presentation, field_name, type_name):
- the_type = get_type_by_name(context, type_name, 'data_types')
- if the_type is not None:
- value = getattr(presentation, field_name)
- if value is not None:
+ value = getattr(presentation, field_name)
+ if value is not None:
+ the_type = get_type_by_name(context, type_name, 'data_types')
+ if the_type is not None:
return coerce_data_type_value(context, presentation, the_type, None, None, value, None)
- else:
- context.validation.report('field "%s" in "%s" refers to unknown data type "%s"'
- % (field_name, presentation._fullname, type_name),
- locator=presentation._locator, level=Issue.BETWEEN_TYPES)
+ else:
+ context.validation.report(u'field "{0}" in "{1}" refers to unknown data type "{2}"'
+ .format(field_name, presentation._fullname, type_name),
+ locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return None
@@ -372,7 +372,7 @@ def get_data_type_name(the_type):
return the_type._name if hasattr(the_type, '_name') else full_type_name(the_type)
-def coerce_value(context, presentation, the_type, entry_schema, constraints, value, aspect=None): # pylint: disable=too-many-return-statements
+def coerce_value(context, presentation, the_type, entry_schema, constraints, value, aspect=None): # pylint: disable=too-many-return-statements
"""
Returns the value after it's coerced to its type, reporting validation errors if it cannot be
coerced.
@@ -394,8 +394,8 @@ def coerce_value(context, presentation, the_type, entry_schema, constraints, val
if the_type == None.__class__:
if value is not None:
- context.validation.report('field "%s" is of type "null" but has a non-null value: %s'
- % (presentation._name, safe_repr(value)),
+ context.validation.report(u'field "{0}" is of type "null" but has a non-null value: {1}'
+ .format(presentation._name, safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_FIELDS)
return None
@@ -498,17 +498,18 @@ def report_issue_for_bad_format(context, presentation, the_type, value, aspect,
if aspect == 'default':
aspect = '"default" value'
elif aspect is not None:
- aspect = '"%s" aspect' % aspect
+ aspect = u'"{0}" aspect'.format(aspect)
if aspect is not None:
- context.validation.report('%s for field "%s" is not a valid "%s": %s'
- % (aspect, presentation._name or presentation._container._name,
- get_data_type_name(the_type), safe_repr(value)),
+ context.validation.report(u'{0} for field "{1}" is not a valid "{2}": {3}'
+ .format(aspect,
+ presentation._name or presentation._container._name,
+ get_data_type_name(the_type), safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_FIELDS,
exception=e)
else:
- context.validation.report('field "%s" is not a valid "%s": %s'
- % (presentation._name or presentation._container._name,
- get_data_type_name(the_type), safe_repr(value)),
+ context.validation.report(u'field "{0}" is not a valid "{1}": {2}'
+ .format(presentation._name or presentation._container._name,
+ get_data_type_name(the_type), safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_FIELDS,
exception=e)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
index ecbfde9..16c49fa 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
@@ -24,6 +24,7 @@ from aria.parser.exceptions import InvalidValueError
from aria.parser.validation import Issue
from aria.modeling.exceptions import CannotEvaluateFunctionException
from aria.modeling.models import (Node, NodeTemplate, Relationship, RelationshipTemplate)
+from aria.modeling.mixins import ParameterMixin
from aria.modeling.functions import (Function, Evaluation)
@@ -43,7 +44,7 @@ class Concat(Function):
if not isinstance(argument, list):
raise InvalidValueError(
- 'function "concat" argument must be a list of string expressions: {0}'
+ u'function "concat" argument must be a list of string expressions: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -84,7 +85,7 @@ class Token(Function):
self.locator = presentation._locator
if (not isinstance(argument, list)) or (len(argument) != 3):
- raise InvalidValueError('function "token" argument must be a list of 3 parameters: {0}'
+ raise InvalidValueError(u'function "token" argument must be a list of 3 parameters: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -95,6 +96,10 @@ class Token(Function):
argument[1])
self.substring_index = parse_int(context, presentation, 'token', 2,
'the 0-based index of the token to return', argument[2])
+ if self.substring_index < 0:
+ raise invalid_value('token', 2, 'a non-negative integer',
+ 'the 0-based index of the token to return', self.substring_index,
+ presentation._locator)
@property
def as_raw(self):
@@ -143,7 +148,7 @@ class GetInput(Function):
'inputs', self.input_property_name)
if the_input is None:
raise InvalidValueError(
- 'function "get_input" argument is not a valid input name: {0}'
+ u'function "get_input" argument is not a valid input name: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -162,7 +167,7 @@ class GetInput(Function):
return Evaluation(value, False) # We never return final evaluations!
raise InvalidValueError(
- 'function "get_input" argument is not a valid input name: {0}'
+ u'function "get_input" argument is not a valid input name: {0}'
.format(safe_repr(self.input_property_name)),
locator=self.locator)
@@ -179,8 +184,8 @@ class GetProperty(Function):
if (not isinstance(argument, list)) or (len(argument) < 2):
raise InvalidValueError(
- 'function "get_property" argument must be a list of at least 2 string expressions: '
- '{0}'.format(safe_repr(argument)),
+ u'function "get_property" argument must be a list of at least 2 string expressions:'
+ u' {0}'.format(safe_repr(argument)),
locator=self.locator)
self.modelable_entity_name = parse_modelable_entity_name(context, presentation,
@@ -224,14 +229,13 @@ class GetProperty(Function):
properties = modelable_entity.properties
nested_property_name_or_index = self.nested_property_name_or_index
- evaluation = get_modelable_entity_parameter(modelable_entity, properties,
- nested_property_name_or_index)
+ evaluation = get_modelable_entity_parameter(properties, nested_property_name_or_index)
if evaluation is not None:
return evaluation
raise InvalidValueError(
- 'function "get_property" could not find "{0}" in modelable entity "{1}"'
- .format('.'.join(self.nested_property_name_or_index), self.modelable_entity_name),
+ u'function "get_property" could not find "{0}" in modelable entity "{1}"'
+ .format(u'.'.join(self.nested_property_name_or_index), self.modelable_entity_name),
locator=self.locator)
@@ -251,8 +255,8 @@ class GetAttribute(Function):
if (not isinstance(argument, list)) or (len(argument) < 2):
raise InvalidValueError(
- 'function "get_attribute" argument must be a list of at least 2 string expressions:'
- ' {0}'.format(safe_repr(argument)),
+ u'function "get_attribute" argument must be a list of at least 2 string '
+ u'expressions: {0}'.format(safe_repr(argument)),
locator=self.locator)
self.modelable_entity_name = parse_modelable_entity_name(context, presentation,
@@ -270,15 +274,14 @@ class GetAttribute(Function):
for modelable_entity in modelable_entities:
attributes = modelable_entity.attributes
nested_attribute_name_or_index = self.nested_attribute_name_or_index
- evaluation = get_modelable_entity_parameter(modelable_entity, attributes,
- nested_attribute_name_or_index)
+ evaluation = get_modelable_entity_parameter(attributes, nested_attribute_name_or_index)
if evaluation is not None:
evaluation.final = False # We never return final evaluations!
return evaluation
raise InvalidValueError(
- 'function "get_attribute" could not find "{0}" in modelable entity "{1}"'
- .format('.'.join(self.nested_attribute_name_or_index), self.modelable_entity_name),
+ u'function "get_attribute" could not find "{0}" in modelable entity "{1}"'
+ .format(u'.'.join(self.nested_attribute_name_or_index), self.modelable_entity_name),
locator=self.locator)
@@ -286,7 +289,7 @@ class GetAttribute(Function):
# Operation
#
-@implements_specification('4.6.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
+@implements_specification('4.6.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
class GetOperationOutput(Function):
"""
The ``get_operation_output`` function is used to retrieve the values of variables exposed /
@@ -298,7 +301,7 @@ class GetOperationOutput(Function):
if (not isinstance(argument, list)) or (len(argument) != 4):
raise InvalidValueError(
- 'function "get_operation_output" argument must be a list of 4 parameters: {0}'
+ u'function "get_operation_output" argument must be a list of 4 parameters: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -327,6 +330,9 @@ class GetOperationOutput(Function):
return {'get_operation_output': [self.modelable_entity_name, interface_name, operation_name,
output_variable_name]}
+ def __evaluate__(self, container):
+ return Evaluation(None)
+
#
# Navigation
@@ -349,7 +355,7 @@ class GetNodesOfType(Function):
node_types = context.presentation.get('service_template', 'node_types')
if (node_types is None) or (self.node_type_name not in node_types):
raise InvalidValueError(
- 'function "get_nodes_of_type" argument is not a valid node type name: {0}'
+ u'function "get_nodes_of_type" argument is not a valid node type name: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -361,14 +367,14 @@ class GetNodesOfType(Function):
return {'get_nodes_of_type': node_type_name}
def __evaluate__(self, container):
- pass
+ return Evaluation(None)
#
# Artifact
#
-@implements_specification('4.8.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
+@implements_specification('4.8.1', 'tosca-simple-1.0') # pylint: disable=abstract-method
class GetArtifact(Function):
"""
The ``get_artifact`` function is used to retrieve artifact location between modelable
@@ -380,7 +386,7 @@ class GetArtifact(Function):
if (not isinstance(argument, list)) or (len(argument) < 2) or (len(argument) > 4):
raise InvalidValueError(
- 'function "get_artifact" argument must be a list of 2 to 4 parameters: {0}'
+ u'function "get_artifact" argument must be a list of 2 to 4 parameters: {0}'
.format(safe_repr(argument)),
locator=self.locator)
@@ -389,10 +395,16 @@ class GetArtifact(Function):
argument[0])
self.artifact_name = parse_string_expression(context, presentation, 'get_artifact', 1,
'the artifact name', argument[1])
- self.location = parse_string_expression(context, presentation, 'get_artifact', 2,
- 'the location or "LOCAL_FILE"', argument[2])
- self.remove = parse_bool(context, presentation, 'get_artifact', 3, 'the removal flag',
- argument[3])
+ if len(argument) > 2:
+ self.location = parse_string_expression(context, presentation, 'get_artifact', 2,
+ 'the location or "LOCAL_FILE"', argument[2])
+ else:
+ self.location = None
+ if len(argument) > 3:
+ self.remove = parse_bool(context, presentation, 'get_artifact', 3, 'the removal flag',
+ argument[3])
+ else:
+ self.remove = None
@property
def as_raw(self):
@@ -400,9 +412,22 @@ class GetArtifact(Function):
if hasattr(artifact_name, 'as_raw'):
artifact_name = as_raw(artifact_name)
location = self.location
- if hasattr(location, 'as_raw'):
- location = as_raw(location)
- return {'get_artifacts': [self.modelable_entity_name, artifact_name, location, self.remove]}
+ if location is not None:
+ if hasattr(location, 'as_raw'):
+ location = as_raw(location)
+ remove = self.remove
+ if hasattr(remove, 'as_raw'):
+ remove = as_raw(remove)
+ if remove is not None:
+ return {'get_artifact': [self.modelable_entity_name, artifact_name, location,
+ remove]}
+ else:
+ return {'get_artifact': [self.modelable_entity_name, artifact_name, location]}
+ else:
+ return {'get_artifact': [self.modelable_entity_name, artifact_name]}
+
+ def __evaluate__(self, container):
+ return Evaluation(None)
#
@@ -422,16 +447,16 @@ def get_function(context, presentation, value):
return False, None
-def parse_string_expression(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
+def parse_string_expression(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
is_function, func = get_function(context, presentation, value)
if is_function:
return func
else:
- value = str(value)
+ value = unicode(value)
return value
-def parse_int(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
+def parse_int(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
if not isinstance(value, int):
try:
value = int(value)
@@ -441,7 +466,7 @@ def parse_int(context, presentation, name, index, explanation, value): # pylint:
return value
-def parse_bool(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
+def parse_bool(context, presentation, name, index, explanation, value): # pylint: disable=unused-argument
if not isinstance(value, bool):
raise invalid_value(name, index, 'a boolean', explanation, value, presentation._locator)
return value
@@ -475,7 +500,7 @@ def parse_modelable_entity_name(context, presentation, name, index, value):
or {}
if (value not in node_templates) and (value not in relationship_templates):
raise InvalidValueError(
- 'function "{0}" parameter {1:d} is not a valid modelable entity name: {2}'
+ u'function "{0}" parameter {1:d} is not a valid modelable entity name: {2}'
.format(name, index + 1, safe_repr(value)),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return value
@@ -548,7 +573,7 @@ def get_modelable_entities(container_holder, name, locator, modelable_entity_nam
return modelable_entities
- raise InvalidValueError('function "{0}" could not find modelable entity "{1}"'
+ raise InvalidValueError(u'function "{0}" could not find modelable entity "{1}"'
.format(name, modelable_entity_name),
locator=locator)
@@ -564,9 +589,9 @@ def get_self(container_holder, name, locator):
(not isinstance(container, NodeTemplate)) and \
(not isinstance(container, Relationship)) and \
(not isinstance(container, RelationshipTemplate)):
- raise InvalidValueError('function "{0}" refers to "SELF" but it is not contained in '
- 'a node or a relationship: {1}'.format(name,
- full_type_name(container)),
+ raise InvalidValueError(u'function "{0}" refers to "SELF" but it is not contained in '
+ u'a node or a relationship: {1}'.format(name,
+ full_type_name(container)),
locator=locator)
return [container]
@@ -586,8 +611,8 @@ def get_hosts(container_holder, name, locator):
container = container_holder.container
if (not isinstance(container, Node)) and (not isinstance(container, NodeTemplate)):
- raise InvalidValueError('function "{0}" refers to "HOST" but it is not contained in '
- 'a node: {1}'.format(name, full_type_name(container)),
+ raise InvalidValueError(u'function "{0}" refers to "HOST" but it is not contained in '
+ u'a node: {1}'.format(name, full_type_name(container)),
locator=locator)
if not isinstance(container, Node):
@@ -611,8 +636,8 @@ def get_source(container_holder, name, locator):
container = container_holder.container
if (not isinstance(container, Relationship)) and \
(not isinstance(container, RelationshipTemplate)):
- raise InvalidValueError('function "{0}" refers to "SOURCE" but it is not contained in '
- 'a relationship: {1}'.format(name, full_type_name(container)),
+ raise InvalidValueError(u'function "{0}" refers to "SOURCE" but it is not contained in '
+ u'a relationship: {1}'.format(name, full_type_name(container)),
locator=locator)
if not isinstance(container, RelationshipTemplate):
@@ -631,8 +656,8 @@ def get_target(container_holder, name, locator):
container = container_holder.container
if (not isinstance(container, Relationship)) and \
(not isinstance(container, RelationshipTemplate)):
- raise InvalidValueError('function "{0}" refers to "TARGET" but it is not contained in '
- 'a relationship: {1}'.format(name, full_type_name(container)),
+ raise InvalidValueError(u'function "{0}" refers to "TARGET" but it is not contained in '
+ u'a relationship: {1}'.format(name, full_type_name(container)),
locator=locator)
if not isinstance(container, RelationshipTemplate):
@@ -642,21 +667,25 @@ def get_target(container_holder, name, locator):
return [container.target_node]
-def get_modelable_entity_parameter(modelable_entity, parameters, nested_parameter_name_or_index):
+def get_modelable_entity_parameter(parameters, nested_parameter_name_or_index):
if not parameters:
return Evaluation(None, True)
found = True
final = True
value = parameters
+ last_container = parameters
for name_or_index in nested_parameter_name_or_index:
if (isinstance(value, dict) and (name_or_index in value)) \
or ((isinstance(value, list) and (name_or_index < len(value)))):
- value = value[name_or_index] # Parameter
- # We are not using Parameter.value, but rather Parameter._value, because we want to make
- # sure to get "final" (it is swallowed by Parameter.value)
- value, final = evaluate(value._value, final, value)
+ value = value[name_or_index]
+ if isinstance(value, ParameterMixin):
+ last_container = value
+ # We are not using Parameter.value, but rather Parameter._value, because we want to
+ # make sure to get "final" (it is swallowed by Parameter.value)
+ value = value._value
+ value, final = evaluate(value, final, last_container)
else:
found = False
break
@@ -665,17 +694,17 @@ def get_modelable_entity_parameter(modelable_entity, parameters, nested_paramete
def invalid_modelable_entity_name(name, index, value, locator, contexts):
- return InvalidValueError('function "{0}" parameter {1:d} can be "{2}" only in {3}'
+ return InvalidValueError(u'function "{0}" parameter {1:d} can be "{2}" only in {3}'
.format(name, index + 1, value, contexts),
locator=locator, level=Issue.FIELD)
def invalid_value(name, index, the_type, explanation, value, locator):
return InvalidValueError(
- 'function "{0}" {1} is not {2}{3}: {4}'
+ u'function "{0}" {1} is not {2}{3}: {4}'
.format(name,
- 'parameter {0:d}'.format(index + 1) if index is not None else 'argument',
+ u'parameter {0:d}'.format(index + 1) if index is not None else 'argument',
the_type,
- ', {0}'.format(explanation) if explanation is not None else '',
+ u', {0}'.format(explanation) if explanation is not None else '',
safe_repr(value)),
locator=locator, level=Issue.FIELD)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/groups.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/groups.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/groups.py
new file mode 100644
index 0000000..1d8013b
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/groups.py
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ..presentation.types import convert_name_to_full_type_name
+
+
+#
+# GroupType
+#
+
+def get_inherited_members(context, presentation):
+ """
+ Returns our target node types if we have them or those of our parent, if we have one
+ (recursively).
+ """
+
+ parent = presentation._get_parent(context)
+
+ node_types = get_inherited_members(context, parent) if parent is not None else []
+
+ our_members = presentation.members
+ if our_members:
+ all_node_types = context.presentation.get('service_template', 'node_types') or {}
+ node_types = []
+
+ for our_member in our_members:
+ if our_member in all_node_types:
+ our_member = convert_name_to_full_type_name(context, our_member, all_node_types)
+ node_types.append(all_node_types[our_member])
+
+ return node_types
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
index 23a03b7..d7538c1 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
@@ -177,8 +177,8 @@ def get_template_interfaces(context, presentation, type_name):
our_interface_assignment, interface_definition, interface_name)
else:
context.validation.report(
- 'interface definition "%s" not declared at %s "%s" in "%s"'
- % (interface_name, type_name, presentation.type, presentation._fullname),
+ u'interface definition "{0}" not declared at {1} "{2}" in "{3}"'
+ .format(interface_name, type_name, presentation.type, presentation._fullname),
locator=our_interface_assignment._locator, level=Issue.BETWEEN_TYPES)
# Check that there are no required inputs that we haven't assigned
@@ -209,7 +209,7 @@ def convert_interface_definition_from_type_to_template(context, presentation, co
return InterfaceAssignment(name=presentation._name, raw=raw, container=container)
-def convert_interface_definition_from_type_to_raw_template(context, presentation): # pylint: disable=invalid-name
+def convert_interface_definition_from_type_to_raw_template(context, presentation): # pylint: disable=invalid-name
raw = OrderedDict()
# Copy default values for inputs
@@ -236,7 +236,7 @@ def convert_interface_definition_from_type_to_raw_template(context, presentation
return raw
-def convert_requirement_interface_definitions_from_type_to_raw_template(context, raw_requirement, # pylint: disable=invalid-name
+def convert_requirement_interface_definitions_from_type_to_raw_template(context, raw_requirement, # pylint: disable=invalid-name
interface_definitions):
if not interface_definitions:
return
@@ -272,10 +272,14 @@ def merge_interface(context, presentation, interface_assignment, our_interface_a
if operation_definition is None:
context.validation.report(
- 'interface definition "%s" refers to an unknown operation "%s" in "%s"'
- % (interface_name, operation_name, presentation._fullname),
+ u'interface definition "{0}" refers to an unknown operation "{1}" in "{2}"'
+ .format(interface_name, operation_name, presentation._fullname),
locator=our_operation_template._locator, level=Issue.BETWEEN_TYPES)
+ # Failsafe to avoid exceptions for invalid assignments
+ if operation_name not in interface_assignment._raw:
+ continue
+
if (our_input_assignments is not None) or (our_implementation is not None):
# Make sure we have the dict
if (operation_name not in interface_assignment._raw) \
@@ -286,6 +290,7 @@ def merge_interface(context, presentation, interface_assignment, our_interface_a
interface_assignment._raw[operation_name]['implementation'] = \
deepcopy_with_locators(our_implementation._raw)
+
# Assign/merge operation inputs
input_definitions = operation_definition.inputs \
if operation_definition is not None else None
@@ -303,15 +308,16 @@ def merge_raw_input_definition(context, the_raw_input, our_input, interface_name
if input_type1 != input_type2:
if operation_name is not None:
context.validation.report(
- 'interface %s "%s" changes operation input "%s.%s" type from "%s" to "%s" in "%s"'
- % (type_name, interface_name, operation_name, our_input._name, input_type1,
- input_type2, presentation._fullname),
+ u'interface {0} "{1}" changes operation input "{2}.{3}" type from "{4}" to "{5}" '
+ u'in "{6}"'
+ .format(type_name, interface_name, operation_name, our_input._name, input_type1,
+ input_type2, presentation._fullname),
locator=input_type2._locator, level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'interface %s "%s" changes input "%s" type from "%s" to "%s" in "%s"'
- % (type_name, interface_name, our_input._name, input_type1, input_type2,
- presentation._fullname),
+ u'interface {0} "{1}" changes input "{2}" type from "{3}" to "{4}" in "{5}"'
+ .format(type_name, interface_name, our_input._name, input_type1, input_type2,
+ presentation._fullname),
locator=input_type2._locator, level=Issue.BETWEEN_TYPES)
# Merge
@@ -405,8 +411,8 @@ def merge_interface_definition(context, interface, our_source, presentation, typ
if (type2 is not None) and not type1._is_descendant(context, type2):
context.validation.report(
- 'interface definition type "{0}" is not a descendant of overridden '
- 'interface definition type "{1}"' \
+ u'interface definition type "{0}" is not a descendant of overridden '
+ u'interface definition type "{1}"' \
.format(type1._name, type2._name),
locator=our_source._locator, level=Issue.BETWEEN_TYPES)
@@ -462,14 +468,14 @@ def assign_raw_inputs(context, values, assignments, definitions, interface_name,
if (definitions is not None) and (input_name not in definitions):
if operation_name is not None:
context.validation.report(
- 'interface definition "%s" assigns a value to an unknown operation input'
- ' "%s.%s" in "%s"'
- % (interface_name, operation_name, input_name, presentation._fullname),
+ u'interface definition "{0}" assigns a value to an unknown operation input'
+ u' "{1}.{2}" in "{3}"'
+ .format(interface_name, operation_name, input_name, presentation._fullname),
locator=assignment._locator, level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'interface definition "%s" assigns a value to an unknown input "%s" in "%s"'
- % (interface_name, input_name, presentation._fullname),
+ u'interface definition "{0}" assigns a value to an unknown input "{1}" in "{2}"'
+ .format(interface_name, input_name, presentation._fullname),
locator=assignment._locator, level=Issue.BETWEEN_TYPES)
definition = definitions.get(input_name) if definitions is not None else None
@@ -498,16 +504,17 @@ def validate_required_inputs(context, presentation, assignment, definition, orig
if value is None:
if operation_name is not None:
context.validation.report(
- 'interface definition "%s" does not assign a value to a required'
- ' operation input "%s.%s" in "%s"'
- % (interface_name, operation_name, input_name, presentation._fullname),
+ u'interface definition "{0}" does not assign a value to a required'
+ u' operation input "{1}.{2}" in "{3}"'
+ .format(interface_name, operation_name, input_name,
+ presentation._fullname),
locator=get_locator(original_assignment, presentation._locator),
level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'interface definition "%s" does not assign a value to a required input'
- ' "%s" in "%s"'
- % (interface_name, input_name, presentation._fullname),
+ u'interface definition "{0}" does not assign a value to a required'
+ u' input "{1}" in "{2}"'
+ .format(interface_name, input_name, presentation._fullname),
locator=get_locator(original_assignment, presentation._locator),
level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
index 9bafeec..6a0af90 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
@@ -88,7 +88,7 @@ def get_assigned_and_defined_parameter_values(context, presentation, field_name)
definition = definitions[name]
values[name] = coerce_parameter_value(context, value, definition, value.value)
else:
- context.validation.report('assignment to undefined {0} "{1}" in "{2}"'
+ context.validation.report(u'assignment to undefined {0} "{1}" in "{2}"'
.format(field_name, name, presentation._fullname),
locator=value._locator, level=Issue.BETWEEN_TYPES)
@@ -148,10 +148,10 @@ def validate_required_values(context, presentation, values, definitions):
if not definitions:
return
for name, definition in definitions.iteritems():
- if getattr(definition, 'required', False) and \
- ((values is None) or (values.get(name) is None)):
- context.validation.report('required property "%s" is not assigned a value in "%s"'
- % (name, presentation._fullname),
+ if getattr(definition, 'required', False) \
+ and ((values is None) or (values.get(name) is None)):
+ context.validation.report(u'required property "{0}" is not assigned a value in "{1}"'
+ .format(name, presentation._fullname),
locator=presentation._get_child_locator('properties'),
level=Issue.BETWEEN_TYPES)
@@ -169,8 +169,8 @@ def merge_raw_parameter_definition(context, presentation, raw_property_definitio
if type1 != type2:
if not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2):
context.validation.report(
- 'property definition type "{0}" is not a descendant of overridden '
- 'property definition type "{1}"' \
+ u'property definition type "{0}" is not a descendant of overridden '
+ u'property definition type "{1}"' \
.format(type1_name, type2._name),
locator=presentation._get_child_locator(field_name, property_name),
level=Issue.BETWEEN_TYPES)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f4f09852/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
index 6bdb5b1..bf1088b 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
@@ -107,24 +107,25 @@ def get_template_requirements(context, presentation):
requirement_assignments.append((requirement_name, requirement_assignment))
elif actual_occurrences > 1:
context.validation.report(
- 'requirement "%s" is allowed only one occurrence in "%s": %d'
- % (requirement_name, presentation._fullname, actual_occurrences),
+ u'requirement "{0}" is allowed only one occurrence in "{1}": {2:d}'
+ .format(requirement_name, presentation._fullname, actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
if not allowed_occurrences.is_in(actual_occurrences):
if allowed_occurrences.value[1] == 'UNBOUNDED':
context.validation.report(
- 'requirement "%s" does not have at least %d occurrences in "%s": has %d'
- % (requirement_name, allowed_occurrences.value[0],
- presentation._fullname, actual_occurrences),
+ u'requirement "{0}" does not have at least {1:d} occurrences in "{3}":'
+ u' has {4:d}'
+ .format(requirement_name, allowed_occurrences.value[0],
+ presentation._fullname, actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
else:
context.validation.report(
- 'requirement "%s" is allowed between %d and %d occurrences in "%s":'
- ' has %d'
- % (requirement_name, allowed_occurrences.value[0],
- allowed_occurrences.value[1], presentation._fullname,
- actual_occurrences),
+ u'requirement "{0}" is allowed between {1:d} and {2:d} occurrences in'
+ u' "{3}": has {4:d}'
+ .format(requirement_name, allowed_occurrences.value[0],
+ allowed_occurrences.value[1], presentation._fullname,
+ actual_occurrences),
locator=presentation._locator, level=Issue.BETWEEN_TYPES)
return requirement_assignments
@@ -134,7 +135,7 @@ def get_template_requirements(context, presentation):
# Utils
#
-def convert_requirement_from_definition_to_assignment(context, requirement_definition, # pylint: disable=too-many-branches
+def convert_requirement_from_definition_to_assignment(context, requirement_definition, # pylint: disable=too-many-branches
our_requirement_assignment, container):
from ..assignments import RequirementAssignment
@@ -174,9 +175,9 @@ def convert_requirement_from_definition_to_assignment(context, requirement_defin
# Make sure the type is derived
if not definition_relationship_type._is_descendant(context, relationship_type):
context.validation.report(
- 'assigned relationship type "%s" is not a descendant of declared relationship type'
- ' "%s"' \
- % (relationship_type._name, definition_relationship_type._name),
+ u'assigned relationship type "{0}" is not a descendant of declared relationship '
+ u' type "{1}"'
+ .format(relationship_type._name, definition_relationship_type._name),
locator=container._locator, level=Issue.BETWEEN_TYPES)
if relationship_type is not None:
@@ -256,9 +257,9 @@ def add_requirement_assignments(context, presentation, requirement_assignments,
relationship_interface_definitions)
requirement_assignments.append((requirement_name, requirement_assignment))
else:
- context.validation.report('requirement "%s" not declared at node type "%s" in "%s"'
- % (requirement_name, presentation.type,
- presentation._fullname),
+ context.validation.report(u'requirement "{0}" not declared at node type "{1}" in "{2}"'
+ .format(requirement_name, presentation.type,
+ presentation._fullname),
locator=our_requirement_assignment._locator,
level=Issue.BETWEEN_TYPES)
@@ -305,10 +306,10 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
coerce_parameter_value(context, presentation, definition, prop)
else:
context.validation.report(
- 'relationship property "%s" not declared at definition of requirement "%s"'
- ' in "%s"'
- % (property_name, requirement._fullname,
- presentation._container._container._fullname),
+ u'relationship property "{0}" not declared at definition of requirement "{1}"'
+ u' in "{2}"'
+ .format(property_name, requirement._fullname,
+ presentation._container._container._fullname),
locator=our_relationship._get_child_locator('properties', property_name),
level=Issue.BETWEEN_TYPES)
@@ -330,10 +331,10 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
interface_definition, interface_name)
else:
context.validation.report(
- 'relationship interface "%s" not declared at definition of requirement "%s"'
- ' in "%s"'
- % (interface_name, requirement._fullname,
- presentation._container._container._fullname),
+ u'relationship interface "{0}" not declared at definition of requirement "{1}"'
+ u' in "{2}"'
+ .format(interface_name, requirement._fullname,
+ presentation._container._container._fullname),
locator=our_relationship._locator, level=Issue.BETWEEN_TYPES)