From 864aa3da573d6d8f63fcb98628d8db2d3970b1ab Mon Sep 17 00:00:00 2001 From: Stan Lagun Date: Thu, 27 Aug 2015 18:58:34 +0300 Subject: [PATCH] Namespace resolution error was fixed For method invocation context of a sender object was used. Then the current type was taken from it and class names were resolved using namespaces of that class. However in situations when contracted method was located in parent class that had different namespace declarations it lead to a wrong namespaces being used. This commit adds information on which class has the contract so that the sender could be upcasted to it first. Change-Id: Ieb4fca4ea7f2c64c7a731b81fee2ccaff1b1a531 Closes-Bug: #1489524 --- murano/dsl/class_loader.py | 2 +- murano/dsl/murano_method.py | 2 +- murano/dsl/murano_object.py | 6 +++--- murano/dsl/typespec.py | 11 ++++++++--- murano/dsl/yaql_integration.py | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/murano/dsl/class_loader.py b/murano/dsl/class_loader.py index 05264b20..d16a1085 100644 --- a/murano/dsl/class_loader.py +++ b/murano/dsl/class_loader.py @@ -71,7 +71,7 @@ class MuranoClassLoader(object): properties = data.get('Properties') or {} for property_name, property_spec in properties.iteritems(): - spec = typespec.PropertySpec(property_spec) + spec = typespec.PropertySpec(property_spec, type_obj) type_obj.add_property(property_name, spec) methods = data.get('Methods') or data.get('Workflow') or {} diff --git a/murano/dsl/murano_method.py b/murano/dsl/murano_method.py index d96ce484..0aac9ba1 100644 --- a/murano/dsl/murano_method.py +++ b/murano/dsl/murano_method.py @@ -68,7 +68,7 @@ class MuranoMethod(dsl_types.MuranoMethod): raise ValueError() name = record.keys()[0] self._arguments_scheme[name] = typespec.ArgumentSpec( - record[name]) + record[name], self.murano_class) self._yaql_function_definition = \ yaql_integration.build_wrapper_function_definition(self) diff --git a/murano/dsl/murano_object.py b/murano/dsl/murano_object.py index 512510fa..30716db5 100644 --- a/murano/dsl/murano_object.py +++ b/murano/dsl/murano_object.py @@ -26,7 +26,7 @@ class MuranoObject(dsl_types.MuranoObject): name=None, known_classes=None, defaults=None, this=None): if known_classes is None: known_classes = {} - self.__owner = owner + self.__owner = owner.real_this if owner else None self.__object_id = object_id or helpers.generate_id() self.__type = murano_class self.__properties = {} @@ -222,7 +222,7 @@ class MuranoObject(dsl_types.MuranoObject): obj = self.cast(mc) values_to_assign.append((obj, spec.validate( - value, context or self.context, self.real_this, + value, self.real_this, self.real_this, default=default))) for obj, value in values_to_assign: obj.__properties[name] = value @@ -240,7 +240,7 @@ class MuranoObject(dsl_types.MuranoObject): return parent.cast(type) except TypeError: continue - raise TypeError('Cannot cast') + raise TypeError('Cannot cast {0} to {1}'.format(self, type)) def __repr__(self): return '<{0} {1} ({2})>'.format( diff --git a/murano/dsl/typespec.py b/murano/dsl/typespec.py index bbef3d7d..a0b0f448 100644 --- a/murano/dsl/typespec.py +++ b/murano/dsl/typespec.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import weakref + from murano.dsl import exceptions from murano.dsl import type_scheme @@ -28,7 +30,8 @@ class PropertyUsages(object): class Spec(object): - def __init__(self, declaration): + def __init__(self, declaration, container_class): + self._container_class = weakref.ref(container_class) self._contract = type_scheme.TypeScheme(declaration['Contract']) self._usage = declaration.get('Usage') or 'In' self._default = declaration.get('Default') @@ -38,10 +41,12 @@ class Spec(object): 'Unknown type {0}. Must be one of ({1})'.format( self._usage, ', '.join(PropertyUsages.All))) - def validate(self, value, context, this, owner, default=None): + def validate(self, value, this, owner, default=None): if default is None: default = self.default - return self._contract(value, context, this, owner, default) + return self._contract( + value, this.cast(self._container_class()).context, + this, owner, default) @property def default(self): diff --git a/murano/dsl/yaql_integration.py b/murano/dsl/yaql_integration.py index e5d0ab2d..38450794 100644 --- a/murano/dsl/yaql_integration.py +++ b/murano/dsl/yaql_integration.py @@ -61,7 +61,7 @@ class ContractedValue(yaqltypes.GenericType): True, None, lambda value, sender, context, *args, **kwargs: self._value_spec.validate( - value, sender.context, helpers.get_this(context), + value, sender.real_this, context[constants.CTX_ARGUMENT_OWNER])) def convert(self, value, *args, **kwargs):