Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-321-clearwater 80bae440b -> a638acdf1 (forced update)


ARIA-324 Refactor ctx proxy access

Our previous use of "." to delimit nested dict keys was wrong (keys
could have a ".") and inflexible. The new implementation uses subsequent
args to move into the dict. The same format can now be used to access
object attributes.

This commit also changes how to support setting values: we must now use
"=" as the penultimate argument with the new value following.

Also fixed: callables will now "grab" the number of args they need
instead of all remaining args, making it possible to do further
inspection on the returned value from the callable. To allow for this,
kwargs are now expected as the first arg rather than the last.

Relatedly, this commit instruments all parameter fields from all models
and fixes related bugs in the instrumentation implementation.

Furthmore, this commit fixes a bad null check in the ctx client, and
also allows it to retrieve Unicode data.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/ddb85e24
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/ddb85e24
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/ddb85e24

Branch: refs/heads/ARIA-321-clearwater
Commit: ddb85e240de400ef81b140240f8bc2036cd24b80
Parents: c2b8e65
Author: Tal Liron <tal.li...@gmail.com>
Authored: Thu Jul 27 17:58:17 2017 -0500
Committer: Tal Liron <tal.li...@gmail.com>
Committed: Thu Jul 27 21:50:50 2017 -0500

----------------------------------------------------------------------
 aria/orchestrator/context/common.py             |  19 ++-
 aria/orchestrator/context/operation.py          |  46 +++---
 .../execution_plugin/ctx_proxy/client.py        |   7 +-
 .../execution_plugin/ctx_proxy/server.py        | 144 +++++++++----------
 aria/orchestrator/workflows/api/task.py         |  13 +-
 aria/storage/collection_instrumentation.py      |  88 ++++++------
 aria/storage/core.py                            |   6 +-
 .../execution_plugin/test_ctx_proxy_server.py   |  96 ++-----------
 .../orchestrator/execution_plugin/test_local.py |  34 ++---
 9 files changed, 193 insertions(+), 260 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py 
b/aria/orchestrator/context/common.py
index f400142..3c5f618 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -38,10 +38,27 @@ class BaseContext(object):
     """
 
     INSTRUMENTATION_FIELDS = (
+        modeling.models.Service.inputs,
+        modeling.models.ServiceTemplate.inputs,
+        modeling.models.Policy.properties,
+        modeling.models.PolicyTemplate.properties,
         modeling.models.Node.attributes,
         modeling.models.Node.properties,
         modeling.models.NodeTemplate.attributes,
-        modeling.models.NodeTemplate.properties
+        modeling.models.NodeTemplate.properties,
+        modeling.models.Group.properties,
+        modeling.models.GroupTemplate.properties,
+        modeling.models.Capability.properties,
+        # TODO ARIA-279: modeling.models.Capability.attributes,
+        modeling.models.CapabilityTemplate.properties,
+        # TODO ARIA-279: modeling.models.CapabilityTemplate.attributes
+        modeling.models.Relationship.properties,
+        modeling.models.Artifact.properties,
+        modeling.models.ArtifactTemplate.properties,
+        modeling.models.Interface.inputs,
+        modeling.models.InterfaceTemplate.inputs,
+        modeling.models.Operation.inputs,
+        modeling.models.OperationTemplate.inputs
     )
 
     class PrefixedLogger(object):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py 
b/aria/orchestrator/context/operation.py
index 7d5f40c..8613ec3 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -48,8 +48,7 @@ class BaseOperationContext(common.BaseContext):
     @property
     def task(self):
         """
-        The task in the model storage
-        :return: Task model
+        The task in the model storage.
         """
         # SQLAlchemy prevents from accessing an object which was created on a 
different thread.
         # So we retrieve the object from the storage if the current thread 
isn't the same as the
@@ -62,7 +61,7 @@ class BaseOperationContext(common.BaseContext):
     @property
     def plugin_workdir(self):
         """
-        A work directory that is unique to the plugin and the deployment id
+        A work directory that is unique to the plugin and the service ID.
         """
         if self.task.plugin is None:
             return None
@@ -120,20 +119,18 @@ class NodeOperationContext(BaseOperationContext):
     """
 
     @property
-    def node_template(self):
+    def node(self):
         """
-        the node of the current operation
-        :return:
+        The node of the current operation.
         """
-        return self.node.node_template
+        return self.model.node.get(self._actor_id)
 
     @property
-    def node(self):
+    def node_template(self):
         """
-        The node instance of the current operation
-        :return:
+        The node template of the current operation.
         """
-        return self.model.node.get(self._actor_id)
+        return self.node.node_template
 
 
 class RelationshipOperationContext(BaseOperationContext):
@@ -142,41 +139,36 @@ class RelationshipOperationContext(BaseOperationContext):
     """
 
     @property
-    def source_node_template(self):
+    def relationship(self):
         """
-        The source node
-        :return:
+        The relationship instance of the current operation.
         """
-        return self.source_node.node_template
+        return self.model.relationship.get(self._actor_id)
 
     @property
     def source_node(self):
         """
-        The source node instance
-        :return:
+        The relationship source node.
         """
         return self.relationship.source_node
 
     @property
-    def target_node_template(self):
+    def source_node_template(self):
         """
-        The target node
-        :return:
+        The relationship source node template.
         """
-        return self.target_node.node_template
+        return self.source_node.node_template
 
     @property
     def target_node(self):
         """
-        The target node instance
-        :return:
+        The relationship target node.
         """
         return self.relationship.target_node
 
     @property
-    def relationship(self):
+    def target_node_template(self):
         """
-        The relationship instance of the current operation
-        :return:
+        The relationship target node template.
         """
-        return self.model.relationship.get(self._actor_id)
+        return self.target_node.node_template

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/execution_plugin/ctx_proxy/client.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/client.py 
b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
index 1310c21..84d66f1 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/client.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
@@ -102,9 +102,12 @@ def main(args=None):
     if args.json_output:
         response = json.dumps(response)
     else:
-        if not response:
+        if response is None:
             response = ''
-        response = str(response)
+        try:
+            response = str(response)
+        except UnicodeEncodeError:
+            response = unicode(response).encode('utf8')
     sys.stdout.write(response)
 
 if __name__ == '__main__':

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/execution_plugin/ctx_proxy/server.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/server.py 
b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
index ca910e0..09cc234 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/server.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
@@ -17,14 +17,13 @@
 ``ctx`` proxy server implementation.
 """
 
-import collections
 import json
-import re
 import socket
 import threading
 import traceback
 import Queue
 import StringIO
+import inspect
 import wsgiref.simple_server
 
 import bottle
@@ -150,43 +149,77 @@ class CtxProxy(object):
         self.close()
 
 
-def _process_ctx_request(ctx, args):
+def _process_ctx_request(ctx, args): # pylint: 
disable=too-many-branches,too-many-statements
     current = ctx
-    num_args = len(args)
     index = 0
+
+    try:
+        equals_index = args.index('=')
+        if equals_index == 0:
+            raise RuntimeError('The "=" argument cannot be first')
+        if equals_index != len(args) - 2:
+            raise RuntimeError('The "=" argument must be penultimate')
+        equals = True
+        equals_key = args[-3]
+        equals_value = args[-1]
+        args = args[:-3]
+    except ValueError:
+        equals = False
+        equals_key = None
+        equals_value = None
+
+    num_args = len(args)
+
     while index < num_args:
         arg = args[index]
         attr = _desugar_attr(current, arg)
-        if attr:
+
+        if attr is not None:
             current = getattr(current, attr)
-        elif isinstance(current, collections.MutableMapping):
-            key = arg
-            path_dict = _PathDictAccess(current)
-            if index + 1 == num_args:
-                # read dict prop by path
-                value = path_dict.get(key)
-                current = value
-            elif index + 2 == num_args:
-                # set dict prop by path
-                value = args[index + 1]
-                path_dict.set(key, value)
-                current = None
-            else:
-                raise RuntimeError('Illegal argument while accessing dict')
-            break
+        elif isinstance(current, list) and _is_int(arg):
+            current = current[int(arg)]
+        elif hasattr(current, '__getitem__'):
+            if equals and (not arg in current):
+                current[arg] = {}
+            current = current[arg]
         elif callable(current):
-            kwargs = {}
-            remaining_args = args[index:]
-            if isinstance(remaining_args[-1], collections.MutableMapping):
-                kwargs = remaining_args[-1]
-                remaining_args = remaining_args[:-1]
-            current = current(*remaining_args, **kwargs)
-            break
+            if isinstance(arg, dict):
+                # Treat the first arg as our kwargs
+                callable_kwargs = arg
+                index += 1
+            else:
+                callable_kwargs = {}
+
+            argspec = inspect.getargspec(current)
+            if argspec.varargs is not None:
+                # Gobble the rest of the args
+                callable_args = args[index:]
+            else:
+                # Take only what we need
+                args_count = len(argspec.args)
+                if inspect.ismethod(current):
+                    # Don't count "self" argument
+                    args_count -= 1
+                callable_args = args[index:index + args_count]
+
+            args_count = len(callable_args)
+            if args_count > 1:
+                index += args_count - 1
+
+            current = current(*callable_args, **callable_kwargs)
         else:
-            raise RuntimeError('{0} cannot be processed in {1}'.format(arg, 
args))
+            raise RuntimeError('`{0}` cannot be processed in {1}'.format(arg, 
args))
         index += 1
+
     if callable(current):
         current = current()
+
+    if equals:
+        if hasattr(current, '__setitem__'):
+            current[equals_key] = equals_value
+        else:
+            setattr(current, equals_key, equals_value)
+
     return current
 
 
@@ -201,55 +234,12 @@ def _desugar_attr(obj, attr):
     return None
 
 
-class _PathDictAccess(object):
-    pattern = re.compile(r"(.+)\[(\d+)\]")
-
-    def __init__(self, obj):
-        self.obj = obj
-
-    def set(self, prop_path, value):
-        obj, prop_name = self._get_parent_obj_prop_name_by_path(prop_path)
-        obj[prop_name] = value
-
-    def get(self, prop_path):
-        value = self._get_object_by_path(prop_path)
-        return value
-
-    def _get_object_by_path(self, prop_path, fail_on_missing=True):
-        # when setting a nested object, make sure to also set all the
-        # intermediate path objects
-        current = self.obj
-        for prop_segment in prop_path.split('.'):
-            match = self.pattern.match(prop_segment)
-            if match:
-                index = int(match.group(2))
-                property_name = match.group(1)
-                if property_name not in current:
-                    self._raise_illegal(prop_path)
-                if not isinstance(current[property_name], list):
-                    self._raise_illegal(prop_path)
-                current = current[property_name][index]
-            else:
-                if prop_segment not in current:
-                    if fail_on_missing:
-                        self._raise_illegal(prop_path)
-                    else:
-                        current[prop_segment] = {}
-                current = current[prop_segment]
-        return current
-
-    def _get_parent_obj_prop_name_by_path(self, prop_path):
-        split = prop_path.split('.')
-        if len(split) == 1:
-            return self.obj, prop_path
-        parent_path = '.'.join(split[:-1])
-        parent_obj = self._get_object_by_path(parent_path, 
fail_on_missing=False)
-        prop_name = split[-1]
-        return parent_obj, prop_name
-
-    @staticmethod
-    def _raise_illegal(prop_path):
-        raise RuntimeError('illegal path: {0}'.format(prop_path))
+def _is_int(arg):
+    try:
+        int(arg)
+    except ValueError:
+        return False
+    return True
 
 
 def _get_unused_port():

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py 
b/aria/orchestrator/workflows/api/task.py
index 4c518fc..ec96d27 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -140,13 +140,18 @@ class OperationTask(BaseTask):
         self.arguments = modeling_utils.merge_parameter_values(arguments,
                                                                
operation.arguments,
                                                                
model_cls=models.Argument)
-        if getattr(self.actor, 'outbound_relationships', None) is not None:
+
+        actor = self.actor
+        if hasattr(actor, '_wrapped'):
+            # Unwrap instrumented model
+            actor = actor._wrapped
+        if isinstance(actor, models.Node):
             self._context_cls = context.operation.NodeOperationContext
-        elif getattr(self.actor, 'source_node', None) is not None:
+        elif isinstance(actor, models.Relationship):
             self._context_cls = context.operation.RelationshipOperationContext
         else:
-            raise exceptions.TaskCreationException('Could not locate valid 
context for '
-                                                   
'{actor.__class__}'.format(actor=self.actor))
+            raise exceptions.TaskCreationException('Could not create valid 
context for '
+                                                   
'{actor.__class__}'.format(actor=actor))
 
     def __repr__(self):
         return self.name

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/storage/collection_instrumentation.py
----------------------------------------------------------------------
diff --git a/aria/storage/collection_instrumentation.py 
b/aria/storage/collection_instrumentation.py
index c90cb18..e04865e 100644
--- a/aria/storage/collection_instrumentation.py
+++ b/aria/storage/collection_instrumentation.py
@@ -146,14 +146,14 @@ class _InstrumentedDict(_InstrumentedCollection, dict):
     def _load(self, dict_=None, **kwargs):
         dict.__init__(
             self,
-            tuple((key, self._raw_value(value)) for key, value in (dict_ or 
{}).items()),
+            tuple((key, self._raw_value(value)) for key, value in (dict_ or 
{}).iteritems()),
             **kwargs)
 
     def update(self, dict_=None, **kwargs):
         dict_ = dict_ or {}
-        for key, value in dict_.items():
+        for key, value in dict_.iteritems():
             self[key] = value
-        for key, value in kwargs.items():
+        for key, value in kwargs.iteritems():
             self[key] = value
 
     def __getitem__(self, key):
@@ -202,9 +202,31 @@ class _InstrumentedList(_InstrumentedCollection, list):
 
 class _WrappedBase(object):
 
-    def __init__(self, wrapped, instrumentation):
+    def __init__(self, wrapped, instrumentation, instrumentation_kwargs=None):
+        """
+        :param wrapped: model to be instrumented
+        :param instrumentation: instrumentation dict
+        :param instrumentation_kwargs: arguments for instrumentation class
+        """
         self._wrapped = wrapped
         self._instrumentation = instrumentation
+        self._instrumentation_kwargs = instrumentation_kwargs or {}
+
+    def _wrap(self, value):
+        if value.__class__ in set(class_.class_ for class_ in 
self._instrumentation):
+            return _create_instrumented_model(
+                value, instrumentation=self._instrumentation, 
**self._instrumentation_kwargs)
+        # Check that the value is a SQLAlchemy model (it should have metadata) 
or a collection
+        elif hasattr(value, 'metadata') or isinstance(value, (dict, list)):
+            return _create_wrapped_model(
+                value, instrumentation=self._instrumentation, 
**self._instrumentation_kwargs)
+        return value
+
+    def __getattr__(self, item):
+        if hasattr(self, '_wrapped'):
+            return self._wrap(getattr(self._wrapped, item))
+        else:
+            super(_WrappedBase, self).__getattribute__(item)
 
 
 class _InstrumentedModel(_WrappedBase):
@@ -213,32 +235,32 @@ class _InstrumentedModel(_WrappedBase):
         """
         The original model.
 
-        :param wrapped: model to be instrumented
         :param mapi: MAPI for the wrapped model
+        :param wrapped: model to be instrumented
+        :param instrumentation: instrumentation dict
+        :param instrumentation_kwargs: arguments for instrumentation class
         """
-        super(_InstrumentedModel, self).__init__(*args, **kwargs)
+        super(_InstrumentedModel, 
self).__init__(instrumentation_kwargs=dict(mapi=mapi),
+                                                 *args, **kwargs)
         self._mapi = mapi
         self._apply_instrumentation()
 
-    def __getattr__(self, item):
-        return_value = getattr(self._wrapped, item)
-        if isinstance(return_value, self._wrapped.__class__):
-            return _create_instrumented_model(return_value, self._mapi, 
self._instrumentation)
-        if isinstance(return_value, (list, dict)):
-            return _create_wrapped_model(return_value, self._mapi, 
self._instrumentation)
-        return return_value
-
     def _apply_instrumentation(self):
         for field in self._instrumentation:
+            if field.parent.class_ != type(self._wrapped):
+                # Only apply to fields of our class
+                continue
+
             field_name = field.key
             field_cls = field.mapper.class_
+
             field = getattr(self._wrapped, field_name)
 
-            # Preserve the original value. e.g. original attributes would be 
located under
-            # _attributes
+            # Preserve the original field, e.g. original "attributes" would be 
located under
+            # "_attributes"
             setattr(self, '_{0}'.format(field_name), field)
 
-            # set instrumented value
+            # Set instrumented value
             if isinstance(field, dict):
                 instrumentation_cls = _InstrumentedDict
             elif isinstance(field, list):
@@ -247,7 +269,7 @@ class _InstrumentedModel(_WrappedBase):
                 # TODO: raise proper error
                 raise exceptions.StorageError(
                     "ARIA supports instrumentation for dict and list. Field 
{field} of the "
-                    "class {model} is of {type} type.".format(
+                    "class `{model}` is of type `{type}`.".format(
                         field=field,
                         model=self._wrapped,
                         type=type(field)))
@@ -262,35 +284,13 @@ class _InstrumentedModel(_WrappedBase):
 
 class _WrappedModel(_WrappedBase):
 
-    def __init__(self, instrumentation_kwargs, *args, **kwargs):
-        """
-        :param instrumented_cls: class to be instrumented
-        :param instrumentation_cls: instrumentation cls
-        :param wrapped: currently wrapped instance
-        :param kwargs: passed to the instrumented class
-        """
-        super(_WrappedModel, self).__init__(*args, **kwargs)
-        self._kwargs = instrumentation_kwargs
-
-    def _wrap(self, value):
-        if value.__class__ in (class_.class_ for class_ in 
self._instrumentation):
-            return _create_instrumented_model(
-                value, instrumentation=self._instrumentation, **self._kwargs)
-        elif hasattr(value, 'metadata') or isinstance(value, (dict, list)):
-            # Basically checks that the value is indeed an sqlmodel (it should 
have metadata)
-            return _create_wrapped_model(
-                value, instrumentation=self._instrumentation, **self._kwargs)
-        return value
-
-    def __getattr__(self, item):
-        if hasattr(self, '_wrapped'):
-            return self._wrap(getattr(self._wrapped, item))
-        else:
-            super(_WrappedModel, self).__getattribute__(item)
-
     def __getitem__(self, item):
         return self._wrap(self._wrapped[item])
 
+    def __iter__(self):
+        for item in self._wrapped.__iter__():
+            yield self._wrap(item)
+
 
 def _create_instrumented_model(original_model, mapi, instrumentation):
     return type('Instrumented{0}'.format(original_model.__class__.__name__),

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/storage/core.py
----------------------------------------------------------------------
diff --git a/aria/storage/core.py b/aria/storage/core.py
index 2a5745e..7e9b201 100644
--- a/aria/storage/core.py
+++ b/aria/storage/core.py
@@ -130,7 +130,7 @@ class ModelStorage(Storage):
         """
         model_name = model_cls.__modelname__
         if model_name in self.registered:
-            self.logger.debug('{name} in already storage 
{self!r}'.format(name=model_name,
+            self.logger.debug('{name} already in storage 
{self!r}'.format(name=model_name,
                                                                           
self=self))
             return
         self.registered[model_name] = self.api(name=model_name,
@@ -151,10 +151,10 @@ class ModelStorage(Storage):
         original_instrumentation = {}
 
         try:
-            for mapi in self.registered.values():
+            for mapi in self.registered.itervalues():
                 original_instrumentation[mapi] = 
copy.copy(mapi._instrumentation)
                 mapi._instrumentation.extend(instrumentation)
             yield self
         finally:
-            for mapi in self.registered.values():
+            for mapi in self.registered.itervalues():
                 mapi._instrumentation[:] = original_instrumentation[mapi]

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py 
b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
index 7ab1bdb..40ffd50 100644
--- a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
+++ b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
@@ -39,26 +39,26 @@ class TestCtxProxy(object):
         assert response == 'value1'
 
     def test_dict_prop_access_get_key_nested(self, server):
-        response = self.request(server, 'node', 'properties', 
'prop2.nested_prop1')
+        response = self.request(server, 'node', 'properties', 'prop2', 
'nested_prop1')
         assert response == 'nested_value1'
 
     def test_dict_prop_access_get_with_list_index(self, server):
-        response = self.request(server, 'node', 'properties', 'prop3[2].value')
+        response = self.request(server, 'node', 'properties', 'prop3', 2, 
'value')
         assert response == 'value_2'
 
     def test_dict_prop_access_set(self, server, ctx):
-        self.request(server, 'node', 'properties', 'prop4.key', 'new_value')
-        self.request(server, 'node', 'properties', 'prop3[2].value', 
'new_value_2')
-        self.request(server, 'node', 'properties', 'prop4.some.new.path',
+        self.request(server, 'node', 'properties', 'prop4', 'key', '=', 
'new_value')
+        self.request(server, 'node', 'properties', 'prop3', 2, 'value', '=', 
'new_value_2')
+        self.request(server, 'node', 'properties', 'prop4', 'some', 'new', 
'path', '=',
                      'some_new_value')
         assert ctx.node.properties['prop4']['key'] == 'new_value'
         assert ctx.node.properties['prop3'][2]['value'] == 'new_value_2'
         assert ctx.node.properties['prop4']['some']['new']['path'] == 
'some_new_value'
 
     def test_illegal_dict_access(self, server):
-        self.request(server, 'node', 'properties', 'prop4.key', 'new_value')
+        self.request(server, 'node', 'properties', 'prop4', 'key', '=', 
'new_value')
         with pytest.raises(RuntimeError):
-            self.request(server, 'node', 'properties', 'prop4.key', 
'new_value', 'what')
+            self.request(server, 'node', 'properties', 'prop4', 'key', '=', 
'new_value', 'what')
 
     def test_method_invocation(self, server):
         args = ['arg1', 'arg2', 'arg3']
@@ -77,7 +77,7 @@ class TestCtxProxy(object):
         kwargs = dict(
             arg4=arg4,
             arg5=arg5)
-        response = self.request(server, 'stub_args', arg1, arg2, kwargs)
+        response = self.request(server, 'stub_args', kwargs, arg1, arg2)
         assert response == dict(
             arg1=arg1,
             arg2=arg2,
@@ -236,10 +236,10 @@ class TestArgumentParsing(object):
         self.assert_valid_output({'key': 1},
                                  "{'key': 1}",
                                  '{"key": 1}')
-        self.assert_valid_output(False, '', 'false')
+        self.assert_valid_output(False, 'False', 'false')
         self.assert_valid_output(True, 'True', 'true')
-        self.assert_valid_output([], '', '[]')
-        self.assert_valid_output({}, '', '{}')
+        self.assert_valid_output([], '[]', '[]')
+        self.assert_valid_output({}, '{}', '{}')
 
     def assert_valid_output(self, response, ex_typed_output, ex_json_output):
         self.mock_response = response
@@ -285,77 +285,3 @@ class TestCtxEntryPoint(object):
                              stderr=subprocess.PIPE)
         p.communicate()
         assert not p.wait()
-
-
-class TestPathDictAccess(object):
-    def test_simple_set(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo', 42)
-        assert obj == {'foo': 42}
-
-    def test_nested_set(self):
-        obj = {'foo': {}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar', 42)
-        assert obj == {'foo': {'bar': 42}}
-
-    def test_set_index(self):
-        obj = {'foo': [None, {'bar': 0}]}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo[1].bar', 42)
-        assert obj == {'foo': [None, {'bar': 42}]}
-
-    def test_set_nonexistent_parent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar', 42)
-        assert obj == {'foo': {'bar': 42}}
-
-    def test_set_nonexistent_parent_nested(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar.baz', 42)
-        assert obj == {'foo': {'bar': {'baz': 42}}}
-
-    def test_simple_get(self):
-        obj = {'foo': 42}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo')
-        assert result == 42
-
-    def test_nested_get(self):
-        obj = {'foo': {'bar': 42}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo.bar')
-        assert result == 42
-
-    def test_nested_get_shadows_dotted_name(self):
-        obj = {'foo': {'bar': 42}, 'foo.bar': 58}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo.bar')
-        assert result == 42
-
-    def test_index_get(self):
-        obj = {'foo': [0, 1]}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo[1]')
-        assert result == 1
-
-    def test_get_nonexistent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo')
-
-    def test_get_by_index_not_list(self):
-        obj = {'foo': {0: 'not-list'}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo[0]')
-
-    def test_get_by_index_nonexistent_parent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo[1]')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/tests/orchestrator/execution_plugin/test_local.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_local.py 
b/tests/orchestrator/execution_plugin/test_local.py
index e64e998..f091194 100644
--- a/tests/orchestrator/execution_plugin/test_local.py
+++ b/tests/orchestrator/execution_plugin/test_local.py
@@ -43,10 +43,10 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.key value
+            ctx node attributes map key = value
             ''',
             windows_script='''
-            ctx node attributes map.key value
+            ctx node attributes map key = value
         ''')
         props = self._run(
             executor, workflow_context,
@@ -57,12 +57,12 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.key1 $key1
-            ctx node attributes map.key2 $key2
+            ctx node attributes map key1 = $key1
+            ctx node attributes map key2 = $key2
             ''',
             windows_script='''
-            ctx node attributes map.key1 %key1%
-            ctx node attributes map.key2 %key2%
+            ctx node attributes map key1 = %key1%
+            ctx node attributes map key2 = %key2%
         ''')
         props = self._run(
             executor, workflow_context,
@@ -81,10 +81,10 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.cwd $PWD
+            ctx node attributes map cwd = $PWD
             ''',
             windows_script='''
-            ctx node attributes map.cwd %CD%
+            ctx node attributes map cwd = %CD%
             ''')
         tmpdir = str(tmpdir)
         props = self._run(
@@ -97,7 +97,7 @@ class TestLocalRunScript(object):
         assert p_map['cwd'] == tmpdir
 
     def test_process_command_prefix(self, executor, workflow_context, tmpdir):
-        use_ctx = 'ctx node attributes map.key value'
+        use_ctx = 'ctx node attributes map key = value'
         python_script = ['import subprocess',
                          'subprocess.Popen("{0}".split(' 
')).communicate()[0]'.format(use_ctx)]
         python_script = '\n'.join(python_script)
@@ -121,12 +121,12 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.arg1 "$1"
-            ctx node attributes map.arg2 $2
+            ctx node attributes map arg1 = "$1"
+            ctx node attributes map arg2 = $2
             ''',
             windows_script='''
-            ctx node attributes map.arg1 %1
-            ctx node attributes map.arg2 %2
+            ctx node attributes map arg1 = %1
+            ctx node attributes map arg2 = %2
             ''')
         props = self._run(
             executor, workflow_context,
@@ -209,10 +209,10 @@ if __name__ == '__main__':
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes key "${input_as_env_var}"
+            ctx node attributes key = "${input_as_env_var}"
             ''',
             windows_script='''
-            ctx node attributes key "%input_as_env_var%"
+            ctx node attributes key = "%input_as_env_var%"
         ''')
         props = self._run(
             executor, workflow_context,
@@ -228,10 +228,10 @@ if __name__ == '__main__':
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes key "${input_as_env_var}"
+            ctx node attributes key = "${input_as_env_var}"
             ''',
             windows_script='''
-            ctx node attributes key "%input_as_env_var%"
+            ctx node attributes key = "%input_as_env_var%"
         ''')
 
         props = self._run(

Reply via email to