You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/05/10 19:31:44 UTC
incubator-ariatosca git commit: Fixes for review comments
Repository: incubator-ariatosca
Updated Branches:
refs/heads/ARIA-139-attributes b9ca7381b -> fc16f6e00
Fixes for review comments
* More comments and improved descriptions
* Added Parameter.owner
* utils/type is much more robust now and consolidates all conversions
and names
* Moved dsl_specification to new utils/specification (because utils/type
uses it)
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/fc16f6e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/fc16f6e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/fc16f6e0
Branch: refs/heads/ARIA-139-attributes
Commit: fc16f6e000e6bd3b8bef840978c0d9265d6cb951
Parents: b9ca738
Author: Tal Liron <ta...@gmail.com>
Authored: Wed May 10 14:28:33 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Wed May 10 14:28:33 2017 -0500
----------------------------------------------------------------------
aria/modeling/contraints.py | 15 --
aria/modeling/service_common.py | 125 +++++++--------
aria/modeling/utils.py | 15 ++
.../execution_plugin/instantiation.py | 2 +-
aria/parser/presentation/fields.py | 3 +-
aria/parser/presentation/presentation.py | 3 +-
aria/parser/presentation/utils.py | 3 +-
aria/parser/specification.py | 39 +----
aria/parser/validation/issue.py | 2 +-
aria/utils/formatting.py | 12 --
aria/utils/specification.py | 53 +++++++
aria/utils/type.py | 157 +++++++++++++++----
.../simple_v1_0/modeling/constraints.py | 23 ++-
.../simple_v1_0/modeling/data_types.py | 5 +-
.../simple_v1_0/modeling/functions.py | 14 +-
15 files changed, 288 insertions(+), 183 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/modeling/contraints.py
----------------------------------------------------------------------
diff --git a/aria/modeling/contraints.py b/aria/modeling/contraints.py
index 1798b09..107b010 100644
--- a/aria/modeling/contraints.py
+++ b/aria/modeling/contraints.py
@@ -26,18 +26,3 @@ class NodeTemplateConstraint(object):
Returns true is the target matches the constraint for the source.
"""
raise NotImplementedError
-
-
-class NodeTemplateContainerHolder(object):
- """
- Wrapper that allows using a :class:`aria.modeling.models.NodeTemplate` model directly as the
- ``container_holder`` argument for :func:`evaluate`.
- """
-
- def __init__(self, node_template):
- self.container = node_template
- self.service = None
-
- @property
- def service_template(self):
- return self.container.service_template
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index af8abda..e9c96a4 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -15,8 +15,6 @@
# pylint: disable=no-self-argument, no-member, abstract-method
-import datetime
-
from sqlalchemy import (
Column,
Text,
@@ -24,9 +22,9 @@ from sqlalchemy import (
)
from sqlalchemy.ext.declarative import declared_attr
-from ..parser import dsl_specification
from ..parser.consumption import ConsumptionContext
from ..utils import (collections, formatting, console, caching)
+from ..utils.type import (canonical_type_name, full_type_name)
from .mixins import (InstanceModelMixin, TemplateModelMixin)
from . import (
relationship,
@@ -71,60 +69,71 @@ class ParameterBase(TemplateModelMixin, caching.HasCachedMethods):
@property
@caching.cachedmethod
- def container(self): # pylint: disable=too-many-return-statements,too-many-branches
+ def owner(self):
"""
- The logical container for this parameter, which would be another model.
+ The sole owner of this parameter, which is another model that relates to it.
- *All* parameters should have a container model. In case this property method fails to find
+ *All* parameters should have an owner model. In case this property method fails to find
it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
"""
- from . import models
-
# Find first non-null relationship
- value = None
for the_relationship in self.__mapper__.relationships:
v = getattr(self, the_relationship.key)
if v:
- value = v[0]
- break
-
- # Convert to logical container
-
- if isinstance(value, models.Operation):
- value = value.interface
- elif isinstance(value, models.OperationTemplate):
- value = value.interface_template
-
- if isinstance(value, models.Interface):
- if value.node:
- return value.node
- elif value.group:
- return value.group
- elif value.relationship:
- value = value.relationship
- elif isinstance(value, models.InterfaceTemplate):
- if value.node_template:
- return value.node_template
- elif value.group_template:
- return value.group_template
- elif value.relationship_template:
- value = value.relationship_template
-
- if isinstance(value, models.Relationship):
- return value.source_node
- elif isinstance(value, models.RelationshipTemplate):
- return value.requirement_template.node_template
- elif isinstance(value, models.Capability) or isinstance(value, models.Artifact):
- return value.node
- elif isinstance(value, models.CapabilityTemplate) \
- or isinstance(value, models.ArtifactTemplate):
- return value.node_template
+ return v[0] # because we are many-to-many, the back reference will be a list
+
+ raise ValueError('orphaned parameter: does not have an owner: {0}'.format(self.name))
- if value is not None:
- return value
- else:
- raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name))
+
+ @property
+ @caching.cachedmethod
+ def container(self): # pylint: disable=too-many-return-statements,too-many-branches
+ """
+ The logical container for this parameter, which would be another model: service, node,
+ group, or policy (or their templates).
+
+ The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in
+ TOSCA.
+
+ *All* parameters should have a container model. In case this property method fails to find
+ it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
+ """
+
+ from . import models
+
+ container = self.owner
+
+ # Extract interface from operation
+ if isinstance(container, models.Operation):
+ container = container.interface
+ elif isinstance(container, models.OperationTemplate):
+ container = container.interface_template
+
+ # Extract from other models
+ if isinstance(container, models.Interface):
+ container = container.node or container.group or container.relationship
+ elif isinstance(container, models.InterfaceTemplate):
+ container = container.node_template or container.group_template \
+ or container.relationship_template
+ elif isinstance(container, models.Capability) or isinstance(container, models.Artifact):
+ container = container.node
+ elif isinstance(container, models.CapabilityTemplate) \
+ or isinstance(container, models.ArtifactTemplate):
+ container = container.node_template
+ elif isinstance(container, models.Task):
+ container = container.actor
+
+ # Extract node from relationship
+ if isinstance(container, models.Relationship):
+ container = container.source_node
+ elif isinstance(container, models.RelationshipTemplate):
+ container = container.requirement_template.node_template
+
+ if container is not None:
+ return container
+
+ raise ValueError('orphaned parameter: does not have a container: {0}'.format(self.name))
@property
@caching.cachedmethod
@@ -197,16 +206,11 @@ class ParameterBase(TemplateModelMixin, caching.HasCachedMethods):
def unwrap(self):
return self.name, self.value
- @dsl_specification('3.2.1-2', 'tosca-simple-1.0')
@classmethod
def wrap(cls, name, value, description=None):
"""
Wraps an arbitrary value as a parameter. The type will be guessed via introspection.
- For primitive types, we will prefer their TOSCA aliases. See the `TOSCA Simple Profile v1.0
- cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
- /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__
-
:param name: Parameter name
:type name: basestring
:param value: Parameter value
@@ -215,20 +219,9 @@ class ParameterBase(TemplateModelMixin, caching.HasCachedMethods):
"""
from . import models
- if value is None:
- type_name = 'null'
- elif isinstance(value, basestring):
- type_name = 'string'
- elif isinstance(value, int):
- type_name = 'integer'
- elif isinstance(value, float):
- type_name = 'float'
- elif isinstance(value, bool):
- type_name = 'boolean'
- elif isinstance(value, datetime.datetime):
- type_name = 'timestamp'
- else:
- type_name = formatting.full_type_name(value)
+ type_name = canonical_type_name(value)
+ if type_name is None:
+ type_name = full_type_name(value)
return models.Parameter(name=name, # pylint: disable=unexpected-keyword-arg
type_name=type_name,
value=value,
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index 5355fc0..0404fe4 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -36,6 +36,21 @@ class ModelJSONEncoder(JSONEncoder):
return JSONEncoder.default(self, o)
+class NodeTemplateContainerHolder(object):
+ """
+ Wrapper that allows using a :class:`aria.modeling.models.NodeTemplate` model directly as the
+ ``container_holder`` argument for :func:`aria.modeling.functions.evaluate`.
+ """
+
+ def __init__(self, node_template):
+ self.container = node_template
+ self.service = None
+
+ @property
+ def service_template(self):
+ return self.container.service_template
+
+
def create_inputs(inputs, template_inputs):
"""
:param inputs: key-value dict
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/orchestrator/execution_plugin/instantiation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/instantiation.py b/aria/orchestrator/execution_plugin/instantiation.py
index ce114f0..c09434e 100644
--- a/aria/orchestrator/execution_plugin/instantiation.py
+++ b/aria/orchestrator/execution_plugin/instantiation.py
@@ -15,7 +15,7 @@
# TODO: this module will eventually be moved to a new "aria.instantiation" package
-from ...utils.formatting import full_type_name
+from ...utils.type import full_type_name
from ...utils.collections import OrderedDict
from ...parser import validation
from ...parser.consumption import ConsumptionContext
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/parser/presentation/fields.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/fields.py b/aria/parser/presentation/fields.py
index da3cb05..7f85723 100644
--- a/aria/parser/presentation/fields.py
+++ b/aria/parser/presentation/fields.py
@@ -21,7 +21,8 @@ from ...exceptions import AriaException
from ...utils.collections import FrozenDict, FrozenList, deepcopy_with_locators, merge, OrderedDict
from ...utils.caching import cachedmethod
from ...utils.console import puts
-from ...utils.formatting import as_raw, safe_repr, full_type_name
+from ...utils.formatting import as_raw, safe_repr
+from ...utils.type import full_type_name
from ...utils.exceptions import print_exception
from ..exceptions import InvalidValueError
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/parser/presentation/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/presentation.py b/aria/parser/presentation/presentation.py
index 0f098b5..644d880 100644
--- a/aria/parser/presentation/presentation.py
+++ b/aria/parser/presentation/presentation.py
@@ -15,7 +15,8 @@
from ...utils.caching import HasCachedMethods
from ...utils.collections import deepcopy_with_locators
-from ...utils.formatting import full_type_name, safe_repr
+from ...utils.formatting import safe_repr
+from ...utils.type import full_type_name
from ...utils.console import puts
from ..validation import Issue
from .null import none_to_null
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/parser/presentation/utils.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/utils.py b/aria/parser/presentation/utils.py
index 74adbd1..fbe971b 100644
--- a/aria/parser/presentation/utils.py
+++ b/aria/parser/presentation/utils.py
@@ -15,7 +15,8 @@
from types import FunctionType
-from ...utils.formatting import full_type_name, safe_repr
+from ...utils.formatting import safe_repr
+from ...utils.type import full_type_name
from ..validation import Issue
from .null import NULL
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/parser/specification.py
----------------------------------------------------------------------
diff --git a/aria/parser/specification.py b/aria/parser/specification.py
index 1df11ce..4734aea 100644
--- a/aria/parser/specification.py
+++ b/aria/parser/specification.py
@@ -17,40 +17,7 @@ import re
from ..extension import parser
from ..utils.collections import OrderedDict
-from ..utils.formatting import full_type_name
-
-_DSL_SPECIFICATIONS = {}
-
-
-def dsl_specification(section, spec):
- """
- Decorator for TOSCA specification.
-
- Used for documentation and standards compliance.
- """
- def decorator(obj):
- specification = _DSL_SPECIFICATIONS.get(spec)
-
- if specification is None:
- specification = {}
- _DSL_SPECIFICATIONS[spec] = specification
-
- if section in specification:
- raise Exception('you cannot specify the same @dsl_specification twice, consider'
- ' adding \'-1\', \'-2\', etc.: %s, %s' % (spec, section))
-
- specification[section] = OrderedDict((
- ('code', full_type_name(obj)),
- ('doc', obj.__doc__)))
-
- try:
- setattr(obj, '_dsl_specifications', {section: section, spec: spec})
- except BaseException:
- pass
-
- return obj
-
- return decorator
+from ..utils.specification import (DSL_SPECIFICATIONS, dsl_specification) # pylint: disable=unused-import
def iter_specifications():
@@ -63,12 +30,10 @@ def iter_specifications():
details['code'] = sections[k]['code']
yield k, _fix_details(sections[k], spec)
- for spec, sections in _DSL_SPECIFICATIONS.iteritems():
+ for spec, sections in DSL_SPECIFICATIONS.iteritems():
yield spec, iter_sections(spec, sections)
-# Utils
-
def _section_key(value):
try:
parts = value.split('-', 1)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/parser/validation/issue.py
----------------------------------------------------------------------
diff --git a/aria/parser/validation/issue.py b/aria/parser/validation/issue.py
index f001efc..db8065d 100644
--- a/aria/parser/validation/issue.py
+++ b/aria/parser/validation/issue.py
@@ -16,7 +16,7 @@
from __future__ import absolute_import # so we can import standard 'collections'
from ...utils.collections import OrderedDict
-from ...utils.formatting import full_type_name
+from ...utils.type import full_type_name
class Issue(object):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/utils/formatting.py
----------------------------------------------------------------------
diff --git a/aria/utils/formatting.py b/aria/utils/formatting.py
index 75652a7..f96a4ce 100644
--- a/aria/utils/formatting.py
+++ b/aria/utils/formatting.py
@@ -71,18 +71,6 @@ class YamlAsRawDumper(yaml.dumper.RoundTripDumper): # pylint: disable=too-many-
return super(YamlAsRawDumper, self).represent_data(data)
-def full_type_name(value):
- """
- The full class name of a type or object.
- """
-
- if not isinstance(value, type):
- value = value.__class__
- module = str(value.__module__)
- name = str(value.__name__)
- return name if module == '__builtin__' else '%s.%s' % (module, name)
-
-
def decode_list(data):
decoded_list = []
for item in data:
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/utils/specification.py
----------------------------------------------------------------------
diff --git a/aria/utils/specification.py b/aria/utils/specification.py
new file mode 100644
index 0000000..0b728c3
--- /dev/null
+++ b/aria/utils/specification.py
@@ -0,0 +1,53 @@
+# 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 .collections import OrderedDict
+
+
+DSL_SPECIFICATIONS = {}
+
+
+def dsl_specification(section, spec):
+ """
+ Decorator for DSL specification.
+
+ Used for documentation and standards compliance.
+ """
+
+ from .type import full_type_name
+
+ def decorator(obj):
+ specification = DSL_SPECIFICATIONS.get(spec)
+
+ if specification is None:
+ specification = {}
+ DSL_SPECIFICATIONS[spec] = specification
+
+ if section in specification:
+ raise Exception('you cannot specify the same @dsl_specification twice, consider'
+ ' adding \'-1\', \'-2\', etc.: {0}, {1}'.format(spec, section))
+
+ specification[section] = OrderedDict((
+ ('code', full_type_name(obj)),
+ ('doc', obj.__doc__)))
+
+ try:
+ setattr(obj, '_dsl_specifications', {section: section, spec: spec})
+ except BaseException:
+ pass
+
+ return obj
+
+ return decorator
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/aria/utils/type.py
----------------------------------------------------------------------
diff --git a/aria/utils/type.py b/aria/utils/type.py
index dad5427..dea7dad 100644
--- a/aria/utils/type.py
+++ b/aria/utils/type.py
@@ -13,49 +13,142 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import datetime
+
+from .specification import dsl_specification
+
+
+BASE_TYPES_TO_CANONICAL_NAMES = {
+ # TOSCA aliases:
+ None.__class__: 'null',
+ basestring: 'string',
+ int: 'integer',
+ float: 'float',
+ bool: 'boolean',
+ list: 'list',
+ tuple: 'list',
+ dict: 'map',
+ datetime.datetime: 'timestamp'
+}
+
+NAMES_TO_CANONICAL_TYPES = {
+ # Python:
+ 'none': None.__class__,
+ 'basestring': unicode,
+ 'str': unicode,
+ 'unicode': unicode,
+ 'int': int,
+ 'float': float, # also a TOSCA alias
+ 'bool': bool,
+ 'list': list, # also a TOSCA alias
+ 'tuple': list,
+ 'dict': dict,
+ 'datetime': datetime.datetime,
+
+ # YAML 1.2:
+ 'tag:yaml.org,2002:null': None.__class__,
+ 'tag:yaml.org,2002:str': unicode,
+ 'tag:yaml.org,2002:integer': int,
+ 'tag:yaml.org,2002:float': float,
+ 'tag:yaml.org,2002:bool': bool,
+
+ # TOSCA aliases:
+ 'null': None.__class__,
+ 'string': unicode,
+ 'integer': int,
+ 'boolean': bool,
+
+ # TOSCA custom types:
+ 'map': dict,
+ 'timestamp': datetime.datetime
+}
+
+
+def full_type_name(value):
+ """
+ The full class name of a type or instance.
+ """
+
+ if not isinstance(value, type):
+ value = value.__class__
+ module = str(value.__module__)
+ name = str(value.__name__)
+ return name if module == '__builtin__' else '{0}.{1}'.format(module, name)
+
+
+@dsl_specification('3.2.1-1', 'tosca-simple-1.0')
+def canonical_type_name(value):
+ """
+ Returns the canonical TOSCA type name of a primitive value, or None if unknown.
+
+ For a list of TOSCA type names, see the `TOSCA Simple Profile v1.0
+ cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
+ /TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__
+ """
+
+ for the_type, name in BASE_TYPES_TO_CANONICAL_NAMES.iteritems():
+ if isinstance(value, the_type):
+ return name
+ return None
+
+
+@dsl_specification('3.2.1-2', 'tosca-simple-1.0')
+def canonical_type(type_name):
+ """
+ Return the canonical type for any Python, YAML, or TOSCA type name or alias, or None if
+ unsupported.
+
+ :param type_name: Type name (case insensitive)
+ """
+
+ return NAMES_TO_CANONICAL_TYPES.get(type_name.lower())
+
def validate_value_type(value, type_name):
"""
- Validate a value is of a specific type.
+ Validate that a value is of a specific type. Supports Python, YAML, and TOSCA type names and
+ aliases.
+
A ValueError will be raised on type mismatch.
- Supports both python and yaml type names.
- """
-
- #TODO add timestamp type?
- name_to_type = {
- 'list': list,
- 'dict': dict,
- 'tuple': tuple,
- 'str': str,
- 'unicode': str,
- 'string': str,
- 'int': int,
- 'integer': int,
- 'bool': bool,
- 'boolean': bool,
- 'float': float
- }
-
- type_ = name_to_type.get(type_name.lower())
- if type_ is None:
- raise RuntimeError('No supported type_name was provided')
-
- if not isinstance(value, type_):
+
+ :param type_name: Type name (case insensitive)
+ """
+
+ the_type = canonical_type(type_name)
+ if the_type is None:
+ raise RuntimeError('Unsupported type name: {0}'.format(type_name))
+
+ # The following Python types do not inherit from the canonical type, but are considered valid
+ if (the_type is unicode) and isinstance(value, str):
+ return
+ if (the_type is list) and isinstance(value, tuple):
+ return
+
+ if not isinstance(value, the_type):
raise ValueError('Value {0} is not of type {1}'.format(value, type_name))
-def convert_value_to_type(str_value, type_name):
+def convert_value_to_type(str_value, python_type_name):
+ """
+ Converts a value to a specific Python primitive type.
+
+ A ValueError will be raised for unsupported types or conversion failure.
+
+ :param python_type_name: Python primitive type name (case insensitive)
+ """
+
+ python_type_name = python_type_name.lower()
try:
- if type_name.lower() in ['str', 'unicode']:
+ if python_type_name in ('str', 'unicode'):
return str_value.decode('utf-8')
- elif type_name.lower() == 'int':
+ elif python_type_name == 'int':
return int(str_value)
- elif type_name.lower() == 'bool':
+ elif python_type_name == 'bool':
return bool(str_value)
- elif type_name.lower() == 'float':
+ elif python_type_name == 'float':
return float(str_value)
else:
- raise ValueError('No supported type_name was provided')
+ raise ValueError('Unsupported Python type name: {0}'.format(python_type_name))
except ValueError:
- raise ValueError('Trying to convert {0} to {1} failed'.format(str_value,
- type_name))
+ raise ValueError('Failed to to convert {0} to {1}'.format(str_value,
+ python_type_name))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
index 46783fe..26ee928 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
@@ -15,7 +15,8 @@
import re
-from aria.modeling.contraints import (NodeTemplateConstraint, NodeTemplateContainerHolder)
+from aria.modeling.contraints import NodeTemplateConstraint
+from aria.modeling.utils import NodeTemplateContainerHolder
from aria.modeling.functions import evaluate
from aria.parser import dsl_specification
@@ -27,23 +28,29 @@ class EvaluatingNodeTemplateConstraint(NodeTemplateConstraint):
constraints.
"""
- def __init__(self, property_name, capability_name, constraint, plural=False):
+ def __init__(self, property_name, capability_name, constraint, as_list=False):
self.property_name = property_name
self.capability_name = capability_name
self.constraint = constraint
- self.plural = plural
+ self.as_list = as_list
def matches(self, source_node_template, target_node_template):
+ # TOSCA node template constraints can refer to either capability properties or node
+ # template properties
if self.capability_name is not None:
+ # Capability property
capability = target_node_template.capability_templates.get(self.capability_name)
value = capability.properties.get(self.property_name) \
- if capability is not None else None
+ if capability is not None else None # Parameter
else:
- value = target_node_template.properties.get(self.property_name)
+ # Node template property
+ value = target_node_template.properties.get(self.property_name) # Parameter
+
value = value.value if value is not None else None
container_holder = NodeTemplateContainerHolder(source_node_template)
- if self.plural:
+
+ if self.as_list:
constraints = []
for constraint in self.constraint:
evaluation = evaluate(constraint, container_holder)
@@ -92,7 +99,7 @@ class LessOrEqual(EvaluatingNodeTemplateConstraint):
class InRange(EvaluatingNodeTemplateConstraint):
def __init__(self, property_name, capability_name, constraint):
- super(InRange, self).__init__(property_name, capability_name, constraint, plural=True)
+ super(InRange, self).__init__(property_name, capability_name, constraint, as_list=True)
def matches_evaluated(self, value, constraints):
lower, upper = constraints
@@ -105,7 +112,7 @@ class InRange(EvaluatingNodeTemplateConstraint):
class ValidValues(EvaluatingNodeTemplateConstraint):
def __init__(self, property_name, capability_name, constraint):
- super(ValidValues, self).__init__(property_name, capability_name, constraint, plural=True)
+ super(ValidValues, self).__init__(property_name, capability_name, constraint, as_list=True)
def matches_evaluated(self, value, constraints):
return value in constraints
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/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 fc86292..d426f9d 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
@@ -16,7 +16,8 @@
import re
from aria.utils.collections import OrderedDict
-from aria.utils.formatting import full_type_name, safe_repr
+from aria.utils.formatting import safe_repr
+from aria.utils.type import full_type_name
from aria.utils.imports import import_fullname
from aria.parser import dsl_specification
from aria.parser.presentation import (get_locator, validate_primitive)
@@ -344,7 +345,7 @@ PRIMITIVE_DATA_TYPES = {
'boolean': bool,
'null': None.__class__}
-@dsl_specification('3.2.1-1', 'tosca-simple-1.0')
+@dsl_specification('3.2.1-3', 'tosca-simple-1.0')
def get_primitive_data_type(type_name):
"""
Many of the types we use in this profile are built-in types from the YAML 1.2 specification
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/fc16f6e0/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 3d0f844..02a018f 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
@@ -17,7 +17,8 @@ from cStringIO import StringIO
import re
from aria.utils.collections import FrozenList
-from aria.utils.formatting import (as_raw, safe_repr, full_type_name)
+from aria.utils.formatting import (as_raw, safe_repr)
+from aria.utils.type import full_type_name
from aria.parser import dsl_specification
from aria.parser.exceptions import InvalidValueError
from aria.parser.validation import Issue
@@ -645,11 +646,12 @@ def get_modelable_entity_parameter(modelable_entity, parameters, nested_paramete
final = True
value = parameters
- for name in nested_parameter_name_or_index:
- if (isinstance(value, dict) and (name in value)) \
- or (isinstance(value, list) and name < len(list)):
- value = value[name]
- # We are not using "value.value" because we want to make sure to get "final"
+ 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)
else:
found = False