added list support

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

Branch: refs/heads/ARIA-258-Convert-runtime-properties-to-attributes
Commit: 82d9616661d1c6797e1d5561a5379b97b0070942
Parents: b2014b9
Author: max-orlov <ma...@gigaspaces.com>
Authored: Mon May 22 15:21:53 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Mon May 22 15:21:53 2017 +0300

----------------------------------------------------------------------
 aria/orchestrator/context/common.py          | 128 ++++++++++++++++------
 tests/orchestrator/context/test_operation.py |  44 ++++++--
 2 files changed, 125 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/82d96166/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py 
b/aria/orchestrator/context/common.py
index d85f284..07596f6 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -202,7 +202,49 @@ class BaseContext(object):
         self.model.log._engine.dispose()
 
 
-class _InstrumentedDict(dict):
+class _InstrumentedCollection(object):
+    def _get_instrumented_collection(self, key, value):
+        if isinstance(value, _InstrumentedCollection):
+            return value
+        elif isinstance(value, dict):
+            return _InstrumentedDict(self._model, self, key, seq=value)
+        elif isinstance(value, list):
+            return _InstrumentedList(self._model, self, key, seq=value)
+
+        return value
+
+    def _raw_value(self, value):
+        if self._item_cls and isinstance(value, self._item_cls):
+            return value.value
+        return value
+
+    def _encapsulate_value(self, key, value):
+        if isinstance(value, self._item_cls):
+            return value
+        # If it is not wrapped
+        return self._item_cls.wrap(key, value)
+
+    def __setitem__(self, key, value):
+        self._set(key, value)
+        if self._item_cls:
+            # We are at the top level
+            field = getattr(self._parent, self._field_name)
+            mapi = getattr(self._model, self._item_cls.__modelname__)
+
+            if key in field:
+                # Is this a existing field
+                value = self._set_parent(field, key, value)
+            else:
+                value = self._set_parent(field, key, 
self._encapsulate_value(key, value))
+
+            mapi.update(value)
+        else:
+            self._set(key, value)
+            # We are not at the top level
+            self._parent[self._field_name] = self
+
+
+class _InstrumentedDict(_InstrumentedCollection, dict):
     def __init__(self, model, parent, field_name=None, item_cls=None, 
seq=None, **kwargs):
         self._model = model
         self._parent = parent
@@ -223,12 +265,7 @@ class _InstrumentedDict(dict):
             self[key] = value
 
     def __getitem__(self, key):
-        value = dict.__getitem__(self, key)
-        if isinstance(value, _InstrumentedDict):
-            return value
-        elif isinstance(value, dict):
-            return _InstrumentedDict(self._model, self, key, seq=value)
-        return value
+        return self._get_instrumented_collection(key, dict.__getitem__(self, 
key))
 
     def values(self):
         return [self[key] for key in self.keys()]
@@ -240,40 +277,55 @@ class _InstrumentedDict(dict):
         return (key for key in self.keys())
 
     def _set(self, key, value):
-        if self._item_cls and isinstance(value, self._item_cls):
-            value = value.value
-        dict.__setitem__(self, key, value)
+        dict.__setitem__(self, key, self._raw_value(value))
 
-    def __setitem__(self, key, value):
-        self._set(key, value)
-        def _set_parent(value):
-            if key in field and isinstance(field[key], self._item_cls):
-                if isinstance(field[key], dict):
-                    field[key].clear()
-                field[key].value = value
-            else:
-                field[key] = value
-            return field[key]
+    def _set_parent(self, field, key, value):
+        if key in field and isinstance(field[key], self._item_cls):
+            if isinstance(field[key], dict):
+                field[key].clear()
+            field[key].value = value
+        else:
+            field[key] = value
+        return field[key]
+
+
+class _InstrumentedList(list, _InstrumentedCollection):
+    def __init__(self, model, parent, field_name=None, item_cls=None, 
seq=None, **kwargs):
+        self._model = model
+        self._parent = parent
+        self._field_name = field_name
+        self._item_cls = item_cls
+        self._load(seq, **kwargs)
+
+    def _load(self, seq=None, **kwargs):
+        seq = list(item for item in seq or [])
+        super(_InstrumentedList, self).__init__(seq)
+
+    def append(self, value):
+        self.insert(len(self), value)
 
+    def insert(self, index, value):
+        list.insert(self, index, self._raw_value(value))
         if self._item_cls:
-            # We are at the top level
             field = getattr(self._parent, self._field_name)
-            mapi = getattr(self._model, self._item_cls.__modelname__)
+            field.insert(index, self._encapsulate_value(index, value))
+        else:
+            self._parent[self._field_name] = self
 
-            if key in field:
-                # Is this a existing field
-                value = _set_parent(value)
-            else:
-                if not isinstance(value, self._item_cls):
-                    # If it is not wrapped
-                    value = self._item_cls.wrap(key, value)
-                value = _set_parent(value)
+    def __getitem__(self, key):
+        return self._get_instrumented_collection(key, list.__getitem__(self, 
key))
 
-            mapi.update(value)
+    def _set(self, key, value):
+        list.__setitem__(self, key, value)
+
+    def _set_parent(self, field, key, value):
+        if key in field and isinstance(field[key], self._item_cls):
+            if isinstance(field[key], list):
+                del field[key]
+            field[key].value = value
         else:
-            dict.__setitem__(self, key, value)
-            # We are not at the top level
-            self._parent[self._field_name] = self
+            field[key] = value
+        return field[key]
 
 
 class InstrumentCollection(object):
@@ -305,6 +357,12 @@ class InstrumentCollection(object):
             setattr(
                 self,
                 self._field_name,
-                _InstrumentedDict(func_self.model, self._actor, 
field_name=self._field_name, item_cls=modeling.models.Parameter, seq=field))
+                _InstrumentedDict(
+                    func_self.model,
+                    self._actor,
+                    field_name=self._field_name,
+                    item_cls=modeling.models.Parameter,
+                    seq=field)
+            )
             return self
         return _wrapper

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/82d96166/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py 
b/tests/orchestrator/context/test_operation.py
index da78199..73efff5 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -503,7 +503,7 @@ def attribute_consuming_operation(ctx, holder_path, **_):
 class MockActor(object):
     def __init__(self):
         self.dict_ = {}
-        self.attributes_list = []
+        self.list_ = []
 
 
 class MockModel(object):
@@ -654,37 +654,57 @@ class TestList(object):
 
     @pytest.fixture
     def list_(self, actor, model):
-        return common._InstrumentedList(
-            actor.attributes_list, model, actor=actor, 
field_name='attributes_list')
+        return common._InstrumentedList(model, actor, field_name='list_', 
item_cls=Parameter)
 
-    def test_insert(self, list_):
+    def test_append(self, actor, list_):
         list_.append(Parameter.wrap('name', 'value1'))
         list_.append('value2')
-
+        assert len(actor.list_) == 2
         assert len(list_) == 2
-        assert isinstance(list_._parent[0], Parameter)
+        assert isinstance(actor.list_[0], Parameter)
         assert list_[0] == 'value1'
 
-        assert isinstance(list_._parent[1], Parameter)
+        assert isinstance(actor.list_[1], Parameter)
         assert list_[1] == 'value2'
 
         list_[0] = 'new_value1'
         list_[1] = 'new_value2'
-        assert isinstance(list_._parent[1], Parameter)
-        assert isinstance(list_._parent[1], Parameter)
+        assert isinstance(actor.list_[1], Parameter)
+        assert isinstance(actor.list_[1], Parameter)
         assert list_[0] == 'new_value1'
         assert list_[1] == 'new_value2'
 
-    def test_insert_into_nested(self, list_):
+    def test_iter(self, list_):
+        list_.append('value1')
+        list_.append('value2')
+        assert sorted(list_) == sorted(['value1', 'value2'])
+
+    def test_insert(self, actor, list_):
+        list_.append('value1')
+        list_.insert(0, 'value2')
+        list_.insert(2, 'value3')
+        list_.insert(10, 'value4')
+        assert sorted(list_) == sorted(['value1', 'value2', 'value3', 
'value4'])
+        assert len(actor.list_) == 4
+
+    def test_set(self, list_):
+        list_.append('value1')
+        list_.append('value2')
+
+        list_[1] = 'value3'
+        assert len(list_) == 2
+        assert sorted(list_) == sorted(['value1', 'value3'])
+
+    def test_insert_into_nested(self, actor, list_):
         list_.append([])
 
         list_[0].append('inner_item')
-        assert isinstance(list_._parent[0], Parameter)
+        assert isinstance(actor.list_[0], Parameter)
         assert len(list_) == 1
         assert list_[0][0] == 'inner_item'
 
         list_[0].append('new_item')
-        assert isinstance(list_._parent[0], Parameter)
+        assert isinstance(actor.list_[0], Parameter)
         assert len(list_) == 1
         assert list_[0][1] == 'new_item'
 

Reply via email to