From 4a3dd52d5d841d0fe86d3719574ee89c6e5e7094 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Mon, 10 Dec 2012 16:52:57 +0100 Subject: [PATCH] Add utility function to create frozenset with unique values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When used instead of a plain call to βfrozensetβ, this would have avoided the issue fixed in commit e2dd6ec. The new function is located in the βcompatβ module as it will be used at module load time in most places and should therefore reside in a place with very few dependencies. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/compat.py | 20 ++++++++++++++++++++ test/ganeti.compat_unittest.py | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/compat.py b/lib/compat.py index 6515af1a0..5f1409e34 100644 --- a/lib/compat.py +++ b/lib/compat.py @@ -146,6 +146,26 @@ def TryToRoman(val, convert=True): else: return val + +def UniqueFrozenset(seq): + """Makes C{frozenset} from sequence after checking for duplicate elements. + + @raise ValueError: When there are duplicate elements + + """ + if isinstance(seq, (list, tuple)): + items = seq + else: + items = list(seq) + + result = frozenset(items) + + if len(items) != len(result): + raise ValueError("Duplicate values found") + + return result + + #: returns the first element of a list-like value fst = operator.itemgetter(0) diff --git a/test/ganeti.compat_unittest.py b/test/ganeti.compat_unittest.py index 54a1c626f..8ed54fe31 100755 --- a/test/ganeti.compat_unittest.py +++ b/test/ganeti.compat_unittest.py @@ -99,5 +99,24 @@ class TestTryToRoman(testutils.GanetiTestCase): self.assertEquals(compat.TryToRoman("19", convert=False), "19") +class TestUniqueFrozenset(unittest.TestCase): + def testDuplicates(self): + for values in [["", ""], ["Hello", "World", "Hello"]]: + self.assertRaises(ValueError, compat.UniqueFrozenset, values) + + def testEmpty(self): + self.assertEqual(compat.UniqueFrozenset([]), frozenset([])) + + def testUnique(self): + self.assertEqual(compat.UniqueFrozenset([1, 2, 3]), frozenset([1, 2, 3])) + + def testGenerator(self): + seq = ("Foo%s" % i for i in range(10)) + self.assertTrue(callable(seq.next)) + self.assertFalse(isinstance(seq, (list, tuple))) + self.assertEqual(compat.UniqueFrozenset(seq), + frozenset(["Foo%s" % i for i in range(10)])) + + if __name__ == "__main__": testutils.GanetiTestProgram() -- GitLab