Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-258-Convert-runtime-properties-to-attributes 9786090d0 -> 
5e5a25389


created a list instrumentation and added some tests


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

Branch: refs/heads/ARIA-258-Convert-runtime-properties-to-attributes
Commit: 5e5a25389f41de9c3a37aaf7e68ff12a987c34a5
Parents: 9786090
Author: max-orlov <[email protected]>
Authored: Wed May 17 18:27:28 2017 +0300
Committer: max-orlov <[email protected]>
Committed: Wed May 17 18:27:28 2017 +0300

----------------------------------------------------------------------
 aria/orchestrator/context/common.py          | 144 ++++++++++++++--------
 aria/orchestrator/context/operation.py       |  12 +-
 tests/orchestrator/context/test_operation.py |  79 +++++++++---
 3 files changed, 159 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5e5a2538/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py 
b/aria/orchestrator/context/common.py
index 83f7215..d41566b 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -201,57 +201,62 @@ class BaseContext(object):
         self.model.log._session.close()
         self.model.log._engine.dispose()
 
-class _Dict(collections.MutableMapping):
-    def __init__(self, actor, model, nested=None):
-        super(_Dict, self).__init__()
+
+class _InstrumentedCollection(object):
+    def __init__(self, actor, attributes, model, nested=None):
+        super(_InstrumentedCollection, self).__init__()
         self._actor = actor
-        self._attributes = self._actor.attributes
+        self._attributes = attributes
         self._model = model
         self._attr_cls = self._model.parameter.model_cls
         self._nested = nested or []
 
+    @property
+    def _nested_value(self):
+        current = self._attributes
+        for k in self._nested:
+            current = current[k]
+        return current.value if isinstance(current, self._attr_cls) else 
current
+
+    def __getitem__(self, index):
+        value = self._nested_value[index] if self._nested else 
self._attributes[index].value
+
+        if isinstance(value, list):
+            return _List(self._actor,
+                         self._attributes,
+                         self._model,
+                         nested=self._nested + [index])
+        elif isinstance(value, dict):
+            return _Dict(self._actor,
+                         self._attributes,
+                         self._model,
+                         nested=self._nested + [index])
+        elif isinstance(value, self._attr_cls):
+            return value.value
+
+        return value
+
     def __delitem__(self, key):
         del self._nested_value[key]
 
-    def __contains__(self, item):
-        for key in self.keys():
-            if item == key:
-                return True
-        return False
-
     def __len__(self):
         return len(self._nested_value)
 
     def __nonzero__(self):
         return bool(self._nested_value)
 
-    def __getitem__(self, item):
-        if self._nested:
-            value = self._nested_value[item]
-        else:
-            value = self._attributes[item].value
-        if isinstance(value, dict):
-            return _Dict(self._actor, self._model, nested=self._nested + 
[item])
-        elif isinstance(value, self._attr_cls):
-            return value.value
-        return value
+
+class _Dict(_InstrumentedCollection, collections.MutableMapping):
 
     def __setitem__(self, key, value):
         if self._nested or key in self._attributes:
             attribute = self._update_attr(key, value)
             self._model.parameter.update(attribute)
         else:
-            attr = self._attr_cls.wrap(key, value)
+            attr = value if isinstance(value, self._attr_cls) else 
self._attr_cls.wrap(key, value)
             self._attributes[key] = attr
             self._model.parameter.put(attr)
 
-    @property
-    def _nested_value(self):
-        current = self._attributes
-        for k in self._nested:
-            current = current[k]
-        return current.value if isinstance(current, self._attr_cls) else 
current
-
     def _update_attr(self, key, value):
         current = self._attributes
 
@@ -272,15 +277,12 @@ class _Dict(collections.MutableMapping):
 
         # Since this a user defined parameter, this doesn't track changes. So 
we override the entire
         # thing.
-        if isinstance(attribute.value, dict):
+        if isinstance(attribute.value, (dict, list)):
             value = attribute.value.copy()
             attribute.value.clear()
         attribute.value = value
         return attribute
 
-    def _unwrap(self, attr):
-        return attr.unwrap() if isinstance(attr, self._attr_cls) else attr
-
     def keys(self):
         dict_ = (self._nested_value.value
                  if isinstance(self._nested_value, self._attr_cls)
@@ -322,26 +324,55 @@ class _Dict(collections.MutableMapping):
     def clear(self):
         self._nested_value.clear()
 
-    def update(self, dict_=None, **kwargs):
-        if dict_:
-            for key, value in dict_.items():
-                self[key] = value
 
-        for key, value in kwargs.items():
-            self[key] = value
+class _List(_InstrumentedCollection, collections.MutableSequence):
 
+    def insert(self, index, value):
+        if self._nested:
+            attribute = self._update_attr(index, value)
+            self._model.parameter.update(attribute)
+        elif len(self._attributes) > index:
+            self._attributes[index].value = value
+            self._model.parameter.update(self._attributes[index])
+        else:
+            attr = value if isinstance(value, self._attr_cls) else 
self._attr_cls.wrap(index, value)
+            self._attributes.insert(index, attr)
+            self._model.parameter.put(self._attributes)
+
+    def __setitem__(self, index, value):
+        return self.insert(index, value)
+
+    def _update_attr(self, index, value):
+        attribute = current = self._attributes[self._nested[0]]
+        for i in self._nested[1:]:
+            current = current[i]
+        if isinstance(current, self._attr_cls):
+            if isinstance(current.value, list):
+                current.value.insert(index, value)
+            else:
+                current.value[index] = value
+        else:
+            current[index] = value
 
-class DecorateAttributes(dict):
+        if isinstance(attribute.value, dict):
+            value = attribute.value.copy()
+            attribute.value.clear()
+            attribute.value = value
+        elif isinstance(attribute.value, list):
+            attribute.value[:] = current.value
 
-    def __init__(self, func):
-        super(DecorateAttributes, self).__init__()
-        self._func = func
-        self._attributes = None
-        self._actor = None
+        return attribute
 
-    @property
-    def attributes(self):
-        return self._attributes
+    def __eq__(self, other):
+        return self._nested_value.__eq__(other)
+
+
+class InstrumentCollection(object):
+
+    def __init__(self, field_name):
+        super(InstrumentCollection, self).__init__()
+        self._field_name = field_name
+        self._actor = None
 
     @property
     def actor(self):
@@ -351,10 +382,15 @@ class DecorateAttributes(dict):
         try:
             return getattr(self._actor, item)
         except AttributeError:
-            return super(DecorateAttributes, self).__getattribute__(item)
-
-    def __call__(self, *args, **kwargs):
-        func_self = args[0]
-        self._actor = self._func(*args, **kwargs)
-        self._attributes = _Dict(self._actor, func_self.model)
-        return self
+            return super(InstrumentCollection, self).__getattribute__(item)
+
+    def __call__(self, func, *args, **kwargs):
+        def _wrapper(func_self, *args, **kwargs):
+            self._actor = func(func_self, *args, **kwargs)
+            field = getattr(self._actor, self._field_name)
+            if isinstance(field, dict):
+                setattr(self, self._field_name, _Dict(self._actor, field, 
func_self.model))
+            elif isinstance(field, list):
+                setattr(self, self._field_name, _List(self._actor, field, 
func_self.model))
+            return self
+        return _wrapper

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5e5a2538/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py 
b/aria/orchestrator/context/operation.py
index f4e8813..fef3ecf 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -105,7 +105,7 @@ class NodeOperationContext(BaseOperationContext):
     """
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def node_template(self):
         """
         the node of the current operation
@@ -114,7 +114,7 @@ class NodeOperationContext(BaseOperationContext):
         return self.node.node_template
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def node(self):
         """
         The node instance of the current operation
@@ -129,7 +129,7 @@ class RelationshipOperationContext(BaseOperationContext):
     """
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def source_node_template(self):
         """
         The source node
@@ -138,7 +138,7 @@ class RelationshipOperationContext(BaseOperationContext):
         return self.source_node.node_template
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def source_node(self):
         """
         The source node instance
@@ -147,7 +147,7 @@ class RelationshipOperationContext(BaseOperationContext):
         return self.relationship.source_node
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def target_node_template(self):
         """
         The target node
@@ -156,7 +156,7 @@ class RelationshipOperationContext(BaseOperationContext):
         return self.target_node.node_template
 
     @property
-    @common.DecorateAttributes
+    @common.InstrumentCollection('attributes')
     def target_node(self):
         """
         The target node instance

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5e5a2538/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py 
b/tests/orchestrator/context/test_operation.py
index 5ce0b22..44823d1 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -502,7 +502,8 @@ def attribute_consuming_operation(ctx, holder_path, **_):
 
 class MockActor(object):
     def __init__(self):
-        self.attributes = {}
+        self.attributes_dict = {}
+        self.attributes_list = []
 
 
 class MockModel(object):
@@ -524,8 +525,8 @@ class TestDict(object):
         return MockModel()
 
     def test_keys(self, model, actor):
-        dict_ = common._Dict(actor, model)
-        actor.attributes.update(
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
+        actor.attributes_dict.update(
             {
                 'key1': Parameter.wrap('key1', 'value1'),
                 'key2': Parameter.wrap('key1', 'value2')
@@ -534,40 +535,40 @@ class TestDict(object):
         assert sorted(dict_.keys()) == sorted(['key1', 'key2'])
 
     def test_values(self, model, actor):
-        dict_ = common._Dict(actor, model)
-        actor.attributes.update({
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
+        actor.attributes_dict.update({
             'key1': Parameter.wrap('key1', 'value1'),
             'key2': Parameter.wrap('key1', 'value2')
         })
         assert sorted(dict_.values()) == sorted(['value1', 'value2'])
 
     def test_items(self, actor, model):
-        dict_ = common._Dict(actor, model)
-        actor.attributes.update({
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
+        actor.attributes_dict.update({
             'key1': Parameter.wrap('key1', 'value1'),
             'key2': Parameter.wrap('key1', 'value2')
         })
         assert sorted(dict_.items()) == sorted([('key1', 'value1'), ('key2', 
'value2')])
 
     def test_iter(self, actor, model):
-        dict_ = common._Dict(actor, model)
-        actor.attributes.update({
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
+        actor.attributes_dict.update({
             'key1': Parameter.wrap('key1', 'value1'),
             'key2': Parameter.wrap('key1', 'value2')
         })
         assert sorted(list(dict_)) == sorted(['key1', 'key2'])
 
     def test_bool(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         assert not dict_
-        actor.attributes.update({
+        actor.attributes_dict.update({
             'key1': Parameter.wrap('key1', 'value1'),
             'key2': Parameter.wrap('key1', 'value2')
         })
         assert dict_
 
     def test_set_item(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         dict_['key1'] = Parameter.wrap('key1', 'value1')
         assert 'key1' in dict_
         assert isinstance(dict_._attributes['key1'], Parameter)
@@ -583,13 +584,13 @@ class TestDict(object):
         assert dict_['key1']['inner_key'] == 'value2'
 
     def test_get_item(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         dict_['key1'] = Parameter.wrap('key1', 'value1')
 
         assert isinstance(dict_._attributes['key1'], Parameter)
 
     def test_update(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         dict_['key1'] = 'value1'
 
         new_dict = {'key2': 'value2'}
@@ -603,7 +604,7 @@ class TestDict(object):
         assert new_dict['key1'] == dict_['key1']
 
     def test_copy(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         dict_['key1'] = 'value1'
 
         new_dict = dict_.copy()
@@ -615,8 +616,54 @@ class TestDict(object):
         assert dict_['key1'] == 'value2'
 
     def test_clear(self, actor, model):
-        dict_ = common._Dict(actor, model)
+        dict_ = common._Dict(actor, actor.attributes_dict, model)
         dict_['key1'] = 'value1'
         dict_.clear()
 
         assert len(dict_) == 0
+
+
+class TestList(object):
+    @pytest.fixture
+    def actor(self):
+        return MockActor()
+
+    @pytest.fixture
+    def model(self):
+        return MockModel()
+
+    def test_insert(self, model, actor):
+        list_ = common._List(actor, actor.attributes_list, model)
+        list_.append(Parameter.wrap('name', 'value1'))
+        list_.append('value2')
+
+        assert len(list_) == 2
+        assert isinstance(list_._attributes[0], Parameter)
+        assert list_[0] == 'value1'
+
+        assert isinstance(list_._attributes[1], Parameter)
+        assert list_[1] == 'value2'
+
+        list_[0] = 'new_value1'
+        list_[1] = 'new_value2'
+        assert isinstance(list_._attributes[1], Parameter)
+        assert isinstance(list_._attributes[1], Parameter)
+        assert list_[0] == 'new_value1'
+        assert list_[1] == 'new_value2'
+
+    def test_insert_into_nested(self, model, actor):
+        list_ = common._List(actor, actor.attributes_list, model)
+        list_.append([])
+
+        list_[0].append('inner_item')
+        assert isinstance(list_._attributes[0], Parameter)
+        assert len(list_) == 1
+        assert list_[0][0] == 'inner_item'
+
+        list_[0].append('new_item')
+        assert isinstance(list_._attributes[0], Parameter)
+        assert len(list_) == 1
+        assert list_[0][1] == 'new_item'
+
+        assert list_[0] == ['inner_item', 'new_item']
+        assert ['inner_item', 'new_item'] == list_[0]

Reply via email to