Revision 6d0accae
b/lib/utils/algo.py | ||
---|---|---|
25 | 25 |
import re |
26 | 26 |
import time |
27 | 27 |
|
28 |
from ganeti import compat |
|
29 |
from ganeti.utils import text |
|
30 |
|
|
28 | 31 |
|
29 | 32 |
_SORTER_GROUPS = 8 |
30 | 33 |
_SORTER_RE = re.compile("^%s(.*)$" % (_SORTER_GROUPS * "(\D+|\d+)?")) |
... | ... | |
169 | 172 |
return new |
170 | 173 |
|
171 | 174 |
|
175 |
def SequenceToDict(seq, key=compat.fst): |
|
176 |
"""Converts a sequence to a dictionary with duplicate detection. |
|
177 |
|
|
178 |
@type seq: sequen |
|
179 |
@param seq: Input sequence |
|
180 |
@type key: callable |
|
181 |
@param key: Function for retrieving dictionary key from sequence element |
|
182 |
@rtype: dict |
|
183 |
|
|
184 |
""" |
|
185 |
keys = map(key, seq) |
|
186 |
|
|
187 |
duplicates = FindDuplicates(keys) |
|
188 |
if duplicates: |
|
189 |
raise ValueError("Duplicate keys found: %s" % text.CommaJoin(duplicates)) |
|
190 |
|
|
191 |
assert len(keys) == len(seq) |
|
192 |
|
|
193 |
return dict(zip(keys, seq)) |
|
194 |
|
|
195 |
|
|
172 | 196 |
class RunningTimeout(object): |
173 | 197 |
"""Class to calculate remaining timeout when doing several operations. |
174 | 198 |
|
b/test/ganeti.utils.algo_unittest.py | ||
---|---|---|
26 | 26 |
import operator |
27 | 27 |
|
28 | 28 |
from ganeti import constants |
29 |
from ganeti import compat |
|
29 | 30 |
from ganeti.utils import algo |
30 | 31 |
|
31 | 32 |
import testutils |
... | ... | |
310 | 311 |
self.assertEqual(result, algo.JoinDisjointDicts(dict_b, dict_a)) |
311 | 312 |
|
312 | 313 |
|
314 |
class TestSequenceToDict(unittest.TestCase): |
|
315 |
def testEmpty(self): |
|
316 |
self.assertEqual(algo.SequenceToDict([]), {}) |
|
317 |
self.assertEqual(algo.SequenceToDict({}), {}) |
|
318 |
|
|
319 |
def testSimple(self): |
|
320 |
data = [(i, str(i), "test%s" % i) for i in range(391)] |
|
321 |
self.assertEqual(algo.SequenceToDict(data), |
|
322 |
dict((i, (i, str(i), "test%s" % i)) |
|
323 |
for i in range(391))) |
|
324 |
|
|
325 |
def testCustomKey(self): |
|
326 |
data = [(i, hex(i), "test%s" % i) for i in range(100)] |
|
327 |
self.assertEqual(algo.SequenceToDict(data, key=compat.snd), |
|
328 |
dict((hex(i), (i, hex(i), "test%s" % i)) |
|
329 |
for i in range(100))) |
|
330 |
self.assertEqual(algo.SequenceToDict(data, |
|
331 |
key=lambda (a, b, val): hash(val)), |
|
332 |
dict((hash("test%s" % i), (i, hex(i), "test%s" % i)) |
|
333 |
for i in range(100))) |
|
334 |
|
|
335 |
def testDuplicate(self): |
|
336 |
self.assertRaises(ValueError, algo.SequenceToDict, |
|
337 |
[(0, 0), (0, 0)]) |
|
338 |
self.assertRaises(ValueError, algo.SequenceToDict, |
|
339 |
[(i, ) for i in range(200)] + [(10, )]) |
|
340 |
|
|
341 |
|
|
313 | 342 |
if __name__ == "__main__": |
314 | 343 |
testutils.GanetiTestProgram() |
Also available in: Unified diff