From 8de1b94d73e285189dda8eec0265b9196f4a3892 Mon Sep 17 00:00:00 2001
From: Sebastian Goscik <sebastian.goscik@live.co.uk>
Date: Thu, 7 Apr 2016 15:08:01 +0100
Subject: [PATCH] enable_disable_list: Added a type to handle
 instrument/result_processor lists

A custom list type now allows "enabling"/"disabling" items by prepending a `~`.
When merged the new state takes priority over the old state.
---
 wlauto/tests/test_utils.py | 17 ++++++++++++++++-
 wlauto/utils/types.py      | 27 +++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/wlauto/tests/test_utils.py b/wlauto/tests/test_utils.py
index 3043eb8d..39c11def 100644
--- a/wlauto/tests/test_utils.py
+++ b/wlauto/tests/test_utils.py
@@ -21,7 +21,7 @@ from nose.tools import raises, assert_equal, assert_not_equal  # pylint: disable
 
 from wlauto.utils.android import check_output
 from wlauto.utils.misc import merge_dicts, merge_lists, TimeoutError
-from wlauto.utils.types import list_or_integer, list_or_bool, caseless_string, arguments
+from wlauto.utils.types import list_or_integer, list_or_bool, caseless_string, arguments, enable_disable_list
 
 
 class TestCheckOutput(TestCase):
@@ -89,3 +89,18 @@ class TestTypes(TestCase):
                      ['--foo', '7', '--bar', 'fizz buzz'])
         assert_equal(arguments(['test', 42]), ['test', '42'])
 
+    def enable_disable_list_test():
+
+        a = enable_disable_list(['qaz', 'qwert', 'asd',  '~fgh', '~seb'])
+        b = enable_disable_list(['qaz', 'xyz',   '~asd', 'fgh',  '~seb'])
+
+        a_into_b = ['qaz', 'xyz', '~seb', 'qwert', 'asd', '~fgh']
+        assert_equal(a.merge_into(b), a_into_b)
+        assert_equal(b.merge_with(a), a_into_b)
+
+        b_into_a = ['qaz', 'qwert', '~seb', 'xyz', '~asd',  'fgh']
+        assert_equal(b.merge_into(a), b_into_a)
+        assert_equal(a.merge_with(b), b_into_a)
+
+        assert_equal(a.values(), ['qaz', 'qwert', 'asd'])
+        assert_equal(b.merge_with(a).values(), ['qaz', 'xyz', 'qwert', 'asd'])
diff --git a/wlauto/utils/types.py b/wlauto/utils/types.py
index 06fcbfef..9c406651 100644
--- a/wlauto/utils/types.py
+++ b/wlauto/utils/types.py
@@ -31,6 +31,7 @@ import math
 import shlex
 from bisect import insort
 from collections import defaultdict
+from copy import copy
 
 from wlauto.utils.misc import isiterable, to_identifier
 from devlib.utils.types import identifier, boolean, integer, numeric, caseless_string
@@ -338,3 +339,29 @@ class prioritylist(object):
 
     def __len__(self):
         return self.size
+
+
+class enable_disable_list(list):
+    def merge_with(self, other):
+        new_self = copy(self)
+        return enable_disable_list.merge(other, new_self)
+
+    def merge_into(self, other):
+        other = copy(other)
+        return enable_disable_list.merge(self, other)
+
+    @staticmethod
+    def merge(source, dest):
+        for item in source:
+            if item not in dest:
+                #Disable previously enabled item
+                if item.startswith('~') and item[1:] in dest:
+                    dest.remove(item[1:])
+                #Enable previously disabled item
+                if not item.startswith('~') and ('~' + item) in dest:
+                    dest.remove('~' + item)
+                dest.append(item)
+        return dest
+
+    def values(self):
+        return [item for item in self if not item.startswith('~')]