You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by mx...@apache.org on 2017/05/22 14:52:09 UTC
[3/4] incubator-ariatosca git commit: added documentation and testing
added documentation and testing
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/4e851057
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/4e851057
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/4e851057
Branch: refs/heads/ARIA-258-Convert-runtime-properties-to-attributes
Commit: 4e8510573d27377d88c9e7811153c2e1c96a9144
Parents: 82d9616
Author: max-orlov <ma...@gigaspaces.com>
Authored: Mon May 22 16:46:50 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Mon May 22 16:46:50 2017 +0300
----------------------------------------------------------------------
aria/orchestrator/context/common.py | 169 ++++++++++++++--------
tests/orchestrator/context/test_operation.py | 48 ++++--
2 files changed, 147 insertions(+), 70 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4e851057/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index 07596f6..a5c01fa 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -203,69 +203,132 @@ class BaseContext(object):
class _InstrumentedCollection(object):
- def _get_instrumented_collection(self, key, value):
+
+ def __init__(self,
+ model,
+ parent,
+ field_name=None,
+ item_cls=None,
+ seq=None,
+ is_top_level=True,
+ **kwargs):
+ self._model = model
+ self._parent = parent
+ self._field_name = field_name
+ self._item_cls = item_cls
+ self._is_top_level = is_top_level
+ self._load(seq, **kwargs)
+
+ def _load(self, seq, **kwargs):
+ """
+ Instantiates the object from existing seq.
+
+ :param seq: the original sequence to load from
+ :return:
+ """
+ raise NotImplementedError
+
+ def _set_field(self, collection, key, value):
+ """
+ enables updating the current change in the ancestors
+ :param collection: the collection to change
+ :param key: the key for the specific field
+ :param value: the new value
+ :return:
+ """
+ raise NotImplementedError
+
+ def _set(self, key, value):
+ """
+ set the changes for the current object (not in the db)
+
+ :param key:
+ :param value:
+ :return:
+ """
+ raise NotImplementedError
+
+ def _instrument(self, key, value):
+ """
+ Instruments any collection to track changes (and ease of access)
+ :param key:
+ :param value:
+ :return:
+ """
if isinstance(value, _InstrumentedCollection):
return value
elif isinstance(value, dict):
- return _InstrumentedDict(self._model, self, key, seq=value)
+ instrumentation_cls = _InstrumentedDict
elif isinstance(value, list):
- return _InstrumentedList(self._model, self, key, seq=value)
+ instrumentation_cls = _InstrumentedList
+ else:
+ return value
- return value
+ return instrumentation_cls(self._model, self, key, self._item_cls, value, False)
def _raw_value(self, value):
- if self._item_cls and isinstance(value, self._item_cls):
+ """
+ Get the raw value.
+ :param value:
+ :return:
+ """
+ if self._is_top_level and isinstance(value, self._item_cls):
return value.value
return value
def _encapsulate_value(self, key, value):
+ """
+ Create a new item cls if needed.
+ :param key:
+ :param value:
+ :return:
+ """
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):
+ """
+ Update the values in both the local and the db locations.
+ :param key:
+ :param value:
+ :return:
+ """
self._set(key, value)
- if self._item_cls:
- # We are at the top level
+ mapi = getattr(self._model, self._item_cls.__modelname__)
+ if self._is_top_level:
field = getattr(self._parent, self._field_name)
- mapi = getattr(self._model, self._item_cls.__modelname__)
-
+ # We are at the top level
if key in field:
# Is this a existing field
- value = self._set_parent(field, key, value)
+ value = self._set_field(field, key, value)
else:
- value = self._set_parent(field, key, self._encapsulate_value(key, value))
-
- mapi.update(value)
+ value = self._set_field(field, key, self._encapsulate_value(key, value))
else:
- self._set(key, value)
# We are not at the top level
- self._parent[self._field_name] = self
+ value = self._set_field(self._parent, self._field_name, self)
+
+ mapi.update(value)
class _InstrumentedDict(_InstrumentedCollection, dict):
- 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 = dict((key, value.value if isinstance(value, self._item_cls) else value)
- for key, value in (seq or {}).items())
- super(_InstrumentedDict, self).__init__(seq, **kwargs)
+ def _load(self, dict_=None, **kwargs):
+ dict.__init__(
+ self,
+ tuple((key, self._raw_value(value)) for key, value in (dict_ or {}).items()),
+ **kwargs)
- def update(self, E=None, **F):
- E = E or {}
- for key, value in E.items():
+ def update(self, dict_=None, **kwargs):
+ dict_ = dict_ or {}
+ for key, value in dict_.items():
self[key] = value
- for key, value in F.items():
+ for key, value in kwargs.items():
self[key] = value
def __getitem__(self, key):
- return self._get_instrumented_collection(key, dict.__getitem__(self, key))
+ return self._instrument(key, dict.__getitem__(self, key))
def values(self):
return [self[key] for key in self.keys()]
@@ -279,53 +342,45 @@ class _InstrumentedDict(_InstrumentedCollection, dict):
def _set(self, key, value):
dict.__setitem__(self, key, self._raw_value(value))
- 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
+ def _set_field(self, collection, key, value):
+ if key in collection and isinstance(collection[key], self._item_cls):
+ if isinstance(collection[key], dict):
+ collection[key].clear()
+ collection[key].value = value
else:
- field[key] = value
- return field[key]
-
+ collection[key] = value
+ return collection[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)
+class _InstrumentedList(_InstrumentedCollection, list):
+ def _load(self, list_=None, **kwargs):
+ list.__init__(self, list(item for item in list_ or []))
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:
+ if self._is_top_level:
field = getattr(self._parent, self._field_name)
field.insert(index, self._encapsulate_value(index, value))
else:
self._parent[self._field_name] = self
def __getitem__(self, key):
- return self._get_instrumented_collection(key, list.__getitem__(self, key))
+ return self._instrument(key, list.__getitem__(self, key))
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
+ def _set_field(self, collection, key, value):
+ if key in collection and isinstance(collection[key], self._item_cls):
+ if isinstance(collection[key], list):
+ del collection[key]
+ collection[key].value = value
else:
- field[key] = value
- return field[key]
+ collection[key] = value
+ return collection[key]
class InstrumentCollection(object):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4e851057/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index 73efff5..86e4a24 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -514,7 +514,7 @@ class MockModel(object):
'update': lambda *args, **kwargs: None})()
-class TestDict(object):
+class ContextSugaring(object):
@pytest.fixture
def actor(self):
@@ -528,6 +528,13 @@ class TestDict(object):
def dict_(self, actor, model):
return common._InstrumentedDict(model, actor, 'dict_', item_cls=Parameter)
+ @pytest.fixture
+ def list_(self, actor, model):
+ return common._InstrumentedList(model, actor, field_name='list_', item_cls=Parameter)
+
+
+class TestDict(ContextSugaring):
+
def test_keys(self, actor, dict_):
dict_.update(
{
@@ -643,18 +650,7 @@ class TestDict(object):
assert len(dict_) == 0
-class TestList(object):
- @pytest.fixture
- def actor(self):
- return MockActor()
-
- @pytest.fixture
- def model(self):
- return MockModel()
-
- @pytest.fixture
- def list_(self, actor, model):
- return common._InstrumentedList(model, actor, field_name='list_', item_cls=Parameter)
+class TestList(ContextSugaring):
def test_append(self, actor, list_):
list_.append(Parameter.wrap('name', 'value1'))
@@ -710,3 +706,29 @@ class TestList(object):
assert list_[0] == ['inner_item', 'new_item']
assert ['inner_item', 'new_item'] == list_[0]
+
+
+class TestDictList(ContextSugaring):
+ def test_dict_in_list(self, actor, list_):
+ list_.append({})
+ assert len(list_) == 1
+ assert isinstance(actor.list_[0], Parameter)
+ assert actor.list_[0].value == {}
+
+ list_[0]['key'] = 'value'
+ assert list_[0]['key'] == 'value'
+ assert len(actor.list_) == 1
+ assert isinstance(actor.list_[0], Parameter)
+ assert actor.list_[0].value['key'] == 'value'
+
+ def test_list_in_dict(self, actor, dict_):
+ dict_['key'] = []
+ assert len(dict_) == 1
+ assert isinstance(actor.dict_['key'], Parameter)
+ assert actor.dict_['key'].value == []
+
+ dict_['key'].append('value')
+ assert dict_['key'][0] == 'value'
+ assert len(actor.dict_) == 1
+ assert isinstance(actor.dict_['key'], Parameter)
+ assert actor.dict_['key'].value[0] == 'value'