Meta values evaluation was fixed

Meta property values were not evaluated.
As a result property value 4 considered to be an integer
but 2+2 to be a string "2+2". This commit fixes 2 things:

1) Adds evaluation to property values making embedded
    YAQL expressions to be evaluated
2) Changes the contexts on which Meta is calculated. Before
    This fix everything was done in caller context thus value
    of the local variables of functions where Meta was accessed
    could be used in Meta definitions

Change-Id: I50de9199e5efa36a668fd3640a016a723326cae7
Closes-Bug: #1555617
This commit is contained in:
Stan Lagun 2016-03-10 15:52:06 +03:00
parent 6bb81bbbf6
commit 188315377b
8 changed files with 42 additions and 17 deletions

View File

@ -287,7 +287,7 @@ class MuranoDslExecutor(object):
self.context_manager.create_package_context(package))
return context
def create_type_context(self, murano_type):
def create_type_context(self, murano_type, caller_context=None):
package_context = self.create_package_context(
murano_type.package)
context = helpers.link_contexts(
@ -295,6 +295,9 @@ class MuranoDslExecutor(object):
self.context_manager.create_type_context(
murano_type)).create_child_context()
context[constants.CTX_TYPE] = murano_type
if caller_context:
context[constants.CTX_NAMES_SCOPE] = caller_context[
constants.CTX_NAMES_SCOPE]
return context
def create_object_context(self, obj, caller_context=None):

View File

@ -41,22 +41,26 @@ from murano.dsl import exceptions
_threads_sequencer = 0
def evaluate(value, context):
def evaluate(value, context, freeze=True):
list_type = tuple if freeze else list
dict_type = yaqlutils.FrozenDict if freeze else dict
set_type = frozenset if freeze else set
if isinstance(value, (dsl_types.YaqlExpression,
yaql.language.expressions.Statement)):
return value(context)
elif isinstance(value, yaqlutils.MappingType):
return yaqlutils.FrozenDict(
(evaluate(d_key, context),
evaluate(d_value, context))
return dict_type(
(evaluate(d_key, context, freeze),
evaluate(d_value, context, freeze))
for d_key, d_value in six.iteritems(value))
elif yaqlutils.is_sequence(value):
return tuple(evaluate(t, context) for t in value)
return list_type(evaluate(t, context, freeze) for t in value)
elif isinstance(value, yaqlutils.SetType):
return frozenset(evaluate(t, context) for t in value)
return set_type(evaluate(t, context, freeze) for t in value)
elif yaqlutils.is_iterable(value):
return tuple(
evaluate(t, context)
return list_type(
evaluate(t, context, freeze)
for t in yaqlutils.limit_iterable(
value, constants.ITERATORS_LIMIT))
elif isinstance(value, dsl_types.MuranoObjectInterface):
@ -524,11 +528,12 @@ def instantiate(data, owner, object_store, context, scope_type,
key, (dsl_types.MuranoTypeReference, dsl_types.MuranoType)):
type_obj = resolve_type(key, scope_type)
props = yaqlutils.filter_parameters_dict(data[key] or {})
props = evaluate(props, context, freeze=False)
return type_obj.new(
owner, object_store, object_store.executor)(
context, **props)
data = updated_dict(defaults, data)
data = evaluate(updated_dict(defaults, data), context, freeze=False)
if '?' not in data:
if not default_type:
raise ValueError('Type information is missing')

View File

@ -143,6 +143,9 @@ class MuranoMethod(dsl_types.MuranoMethod, meta.MetaProvider):
return method._meta
if self._meta_values is None:
executor = helpers.get_executor(context)
context = executor.create_type_context(
self.declaring_type, caller_context=context)
self._meta_values = meta.merge_providers(
self.declaring_type, meta_producer, context)
return self._meta_values
@ -204,6 +207,10 @@ class MuranoMethodArgument(dsl_types.MuranoMethodArgument, typespec.Spec,
return self._arg_name
def get_meta(self, context):
executor = helpers.get_executor(context)
context = executor.create_type_context(
self.murano_method.declaring_type, caller_context=context)
return self._meta.get_meta(context)
def __repr__(self):

View File

@ -208,6 +208,8 @@ class MuranoPackage(dsl_types.MuranoPackage, dslmeta.MetaProvider):
def get_meta(self, context):
if not self._meta:
return []
executor = helpers.get_executor(context)
context = executor.create_package_context(self)
return self._meta.get_meta(context)
def __repr__(self):

View File

@ -19,6 +19,7 @@ import six
from murano.dsl import dsl_types
from murano.dsl import exceptions
from murano.dsl import helpers
from murano.dsl import meta
from murano.dsl import typespec
@ -60,6 +61,10 @@ class MuranoProperty(dsl_types.MuranoProperty, typespec.Spec,
return prop._meta
if self._meta_values is None:
executor = helpers.get_executor(context)
context = executor.create_type_context(
self.declaring_type, caller_context=context)
self._meta_values = meta.merge_providers(
self.declaring_type, meta_producer, context)
return self._meta_values

View File

@ -429,6 +429,9 @@ class MuranoClass(dsl_types.MuranoClass, MuranoType, dslmeta.MetaProvider):
def get_meta(self, context):
if self._meta_values is None:
executor = helpers.get_executor(context)
context = executor.create_type_context(
self, caller_context=context)
self._meta_values = dslmeta.merge_providers(
self, lambda cls: cls._meta, context)
return self._meta_values

View File

@ -176,11 +176,11 @@ Properties:
val: 4
Methods:
testClassInheritedMeta:
testClassMultiMeta:
Body:
- Return: typeinfo($).meta.where($ is InheritedMultiMeta).val
testClassNotInheritedMeta:
testClassSingleMeta:
Body:
- Return: typeinfo($).meta.
where($ is SingleMeta or $ is InheritedSingleMeta).val
@ -227,7 +227,7 @@ Methods:
- InheritedSingleMeta:
val: 8
- SingleMeta:
val: 9
val: 8 + 1
Arguments:
arg:

View File

@ -22,13 +22,13 @@ class TestMeta(test_case.DslTestCase):
super(TestMeta, self).setUp()
self._runner = self.new_runner(om.Object('metatests.TestMeta'))
def test_class_inherited_meta(self):
def test_class_multi_meta(self):
self.assertItemsEqual(
[4, 1, 111, 2], self._runner.testClassInheritedMeta())
[4, 1, 111, 2], self._runner.testClassMultiMeta())
def test_class_not_inherited_meta(self):
def test_class_single_meta(self):
self.assertItemsEqual(
[5, 6], self._runner.testClassNotInheritedMeta())
[5, 6], self._runner.testClassSingleMeta())
def test_parent_class_not_inherited_meta(self):
self.assertEqual(3, self._runner.testParentClassNotInheritedMeta())