diff --git a/lib/utils.py b/lib/utils.py index 73d1bbb8ec3b9520d0af54750140e650274eaca7..f9f5f1b39971f3ebd96a30e69ddf37e79c4aa49a 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -1002,3 +1002,12 @@ def any(seq, pred=bool): for elem in itertools.ifilter(pred, seq): return True return False + + +def UniqueSequence(seq): + """Returns a list with unique elements. + + Element order is preserved. + """ + seen = set() + return [i for i in seq if i not in seen and not seen.add(i)] diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py index 88920671a99bf3c572933bb544a2b64dbb13f40b..8ec8be070422f1b0c744e3c9c66b8f01c0c6d3b1 100755 --- a/test/ganeti.utils_unittest.py +++ b/test/ganeti.utils_unittest.py @@ -608,5 +608,28 @@ class TestNewUUID(unittest.TestCase): self.failUnless(self._re_uuid.match(utils.NewUUID())) +class TestUniqueSequence(unittest.TestCase): + """Test case for UniqueSequence""" + + def _test(self, input, expected): + self.assertEqual(utils.UniqueSequence(input), expected) + + def runTest(self): + # Ordered input + self._test([1, 2, 3], [1, 2, 3]) + self._test([1, 1, 2, 2, 3, 3], [1, 2, 3]) + self._test([1, 2, 2, 3], [1, 2, 3]) + self._test([1, 2, 3, 3], [1, 2, 3]) + + # Unordered input + self._test([1, 2, 3, 1, 2, 3], [1, 2, 3]) + self._test([1, 1, 2, 3, 3, 1, 2], [1, 2, 3]) + + # Strings + self._test(["a", "a"], ["a"]) + self._test(["a", "b"], ["a", "b"]) + self._test(["a", "b", "a"], ["a", "b"]) + + if __name__ == '__main__': unittest.main()