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 <[email protected]> Authored: Wed May 10 14:28:33 2017 -0500 Committer: Tal Liron <[email protected]> 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
