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