Github user AviaE commented on a diff in the pull request:
https://github.com/apache/incubator-ariatosca/pull/142#discussion_r120004996
--- Diff: aria/modeling/mixins.py ---
@@ -140,3 +144,211 @@ class TemplateModelMixin(InstanceModelMixin):
def instantiate(self, container):
raise NotImplementedError
+
+
+class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
+ """
+ Represents a typed value. The value can contain nested intrinsic
functions.
+
+ This model can be used as the ``container_holder`` argument for
:func:`functions.evaluate`.
+
+ :ivar name: Name
+ :vartype name: basestring
+ :ivar type_name: Type name
+ :vartype type_name: basestring
+ :ivar value: Value
+ :ivar description: Description
+ :vartype description: basestring
+ """
+
+ __tablename__ = 'parameter'
+
+ name = Column(Text)
+ type_name = Column(Text)
+ description = Column(Text)
+ _value = Column(PickleType)
+
+ @property
+ def value(self):
+ value = self._value
+ if value is not None:
+ evaluation = functions.evaluate(value, self)
+ if evaluation is not None:
+ value = evaluation.value
+ return value
+
+ @value.setter
+ def value(self, value):
+ self._value = value
+
+ @property
+ @caching.cachedmethod
+ def owner(self):
+ """
+ The sole owner of this parameter, which is another model that
relates to it.
+
+ *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.
+ """
+
+ # Find first non-null relationship
+ for the_relationship in self.__mapper__.relationships:
+ v = getattr(self, the_relationship.key)
+ if v:
+ return v
+
+ raise ValueError('orphaned {class_name}: does not have an owner:
{name}'.format(
+ class_name=type(self).__name__, name=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
+ def service(self):
+ """
+ The :class:`Service` containing this parameter, or None if not
contained in a service.
+ """
+
+ from . import models
+ container = self.container
+ if isinstance(container, models.Service):
+ return container
+ elif hasattr(container, 'service'):
+ return container.service
+ return None
+
+ @property
+ @caching.cachedmethod
+ def service_template(self):
+ """
+ The :class:`ServiceTemplate` containing this parameter, or None if
not contained in a
+ service template.
+ """
+
+ from . import models
+ container = self.container
+ if isinstance(container, models.ServiceTemplate):
+ return container
+ elif hasattr(container, 'service_template'):
+ return container.service_template
+ return None
+
+ @property
+ def as_raw(self):
+ return collections.OrderedDict((
+ ('name', self.name),
+ ('type_name', self.type_name),
+ ('value', self.value),
+ ('description', self.description)))
+
+ def instantiate(self, container):
+ return self.__class__(name=self.name, # pylint:
disable=unexpected-keyword-arg
+ type_name=self.type_name,
+ _value=self._value,
+ description=self.description)
+
+ def coerce_values(self, report_issues):
+ value = self._value
+ if value is not None:
+ evaluation = functions.evaluate(value, self, report_issues)
+ if (evaluation is not None) and evaluation.final:
+ # A final evaluation can safely replace the existing value
+ self._value = evaluation.value
+
+ def dump(self):
+ context = ConsumptionContext.get_thread_local()
+ if self.type_name is not None:
+ console.puts('{0}: {1} ({2})'.format(
+ context.style.property(self.name),
+ context.style.literal(formatting.as_raw(self.value)),
+ context.style.type(self.type_name)))
+ else:
+ console.puts('{0}: {1}'.format(
+ context.style.property(self.name),
+ context.style.literal(formatting.as_raw(self.value))))
+ if self.description:
+ console.puts(context.style.meta(self.description))
+
+ @property
+ def unwrapped(self):
+ return self.name, self.value
+
+ @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
+ :param description: Description (optional)
+ :type description: basestring
+ """
+
+ type_name = canonical_type_name(value)
+ if type_name is None:
+ type_name = full_type_name(value)
+ return cls(name=name, # pylint: disable=unexpected-keyword-arg
+ type_name=type_name,
+ value=value,
+ description=description)
+
+ def as_other_parameter_model(self, other_model_cls):
--- End diff --
We decided on keeping this mechanism as is.
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---