Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of negations in applications array #9

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions reclass/datatypes/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ class Applications(Classes):
a reference of the negation is kept, in case the instance is later used to
extend another instance, in which case the negations should apply to the
instance to be extended.

Negations are dropped after they've been applied once, so that patterns like

```
applications:
- item

applications:
- ~item

applications:
- item
```

result in `item` being present in the final list.
'''
DEFAULT_NEGATION_PREFIX = '~'

Expand All @@ -37,12 +52,17 @@ def append_if_new(self, item):
self._assert_is_string(item)
if item.startswith(self.negation_prefix):
item = item[self._offset:]
self._negations.append(item)
try:
self._items.remove(item)
except ValueError:
pass
# Only keep the negation if we couldn't remove the indicated item.
self._negations.append(item)
elif item in self._negations:
# Remove previously negated items from the negations list instead of
# inserting them into the list.
self._negations.remove(item)
else:
# Insert non-negated items if they're not in our negations list already.
super(Applications, self)._append_if_new(item)

def merge_unique(self, iterable):
Expand All @@ -53,6 +73,8 @@ def merge_unique(self, iterable):
try:
self._items.remove(negation)
except ValueError:
# only remember negations which we didn't process during the merge
self._negations.append(negation)
pass
iterable = iterable.as_list()
for i in iterable:
Expand Down
2 changes: 2 additions & 0 deletions reclass/tests/data/07/classes/cls1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
applications:
- ~foo
2 changes: 2 additions & 0 deletions reclass/tests/data/07/classes/cls2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
applications:
- foo
3 changes: 3 additions & 0 deletions reclass/tests/data/07/classes/global.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
classes:
- cls2
- cls1
2 changes: 2 additions & 0 deletions reclass/tests/data/07/classes/override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
applications:
- foo
10 changes: 10 additions & 0 deletions reclass/tests/data/07/nodes/A.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
classes:
- cls1
- cls2

applications:
- foo

parameters:
expected_apps:
- foo
6 changes: 6 additions & 0 deletions reclass/tests/data/07/nodes/B.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
classes:
- cls2
- cls1

parameters:
expected_apps: []
10 changes: 10 additions & 0 deletions reclass/tests/data/07/nodes/C.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
classes:
- cls2
- cls1

applications:
- foo

parameters:
expected_apps:
- foo
7 changes: 7 additions & 0 deletions reclass/tests/data/07/nodes/D.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
classes:
- global
- override

parameters:
expected_apps:
- foo
13 changes: 13 additions & 0 deletions reclass/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,18 @@ def test_application_removal(self):
self.assertEqual(A_node['applications'], A_node['parameters']['expected_apps'])
self.assertEqual(B_node['applications'], B_node['parameters']['expected_apps'])

def test_application_removal_before_insertion(self):
reclass = self._core('07')

A_node = reclass.nodeinfo('A')
B_node = reclass.nodeinfo('B')
C_node = reclass.nodeinfo('C')
D_node = reclass.nodeinfo('D')

self.assertEqual(A_node['applications'], A_node['parameters']['expected_apps'])
self.assertEqual(B_node['applications'], B_node['parameters']['expected_apps'])
self.assertEqual(C_node['applications'], C_node['parameters']['expected_apps'])
self.assertEqual(D_node['applications'], D_node['parameters']['expected_apps'])

if __name__ == '__main__':
unittest.main()