1 |
|
---|
2 | import unittest
|
---|
3 | from test import test_support
|
---|
4 | import gc
|
---|
5 | import weakref
|
---|
6 | import operator
|
---|
7 | import copy
|
---|
8 | import pickle
|
---|
9 | from random import randrange, shuffle
|
---|
10 | import sys
|
---|
11 | import collections
|
---|
12 |
|
---|
13 | class PassThru(Exception):
|
---|
14 | pass
|
---|
15 |
|
---|
16 | def check_pass_thru():
|
---|
17 | raise PassThru
|
---|
18 | yield 1
|
---|
19 |
|
---|
20 | class BadCmp:
|
---|
21 | def __hash__(self):
|
---|
22 | return 1
|
---|
23 | def __cmp__(self, other):
|
---|
24 | raise RuntimeError
|
---|
25 |
|
---|
26 | class ReprWrapper:
|
---|
27 | 'Used to test self-referential repr() calls'
|
---|
28 | def __repr__(self):
|
---|
29 | return repr(self.value)
|
---|
30 |
|
---|
31 | class HashCountingInt(int):
|
---|
32 | 'int-like object that counts the number of times __hash__ is called'
|
---|
33 | def __init__(self, *args):
|
---|
34 | self.hash_count = 0
|
---|
35 | def __hash__(self):
|
---|
36 | self.hash_count += 1
|
---|
37 | return int.__hash__(self)
|
---|
38 |
|
---|
39 | class TestJointOps(unittest.TestCase):
|
---|
40 | # Tests common to both set and frozenset
|
---|
41 |
|
---|
42 | def setUp(self):
|
---|
43 | self.word = word = 'simsalabim'
|
---|
44 | self.otherword = 'madagascar'
|
---|
45 | self.letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
---|
46 | self.s = self.thetype(word)
|
---|
47 | self.d = dict.fromkeys(word)
|
---|
48 |
|
---|
49 | def test_new_or_init(self):
|
---|
50 | self.assertRaises(TypeError, self.thetype, [], 2)
|
---|
51 | self.assertRaises(TypeError, set().__init__, a=1)
|
---|
52 |
|
---|
53 | def test_uniquification(self):
|
---|
54 | actual = sorted(self.s)
|
---|
55 | expected = sorted(self.d)
|
---|
56 | self.assertEqual(actual, expected)
|
---|
57 | self.assertRaises(PassThru, self.thetype, check_pass_thru())
|
---|
58 | self.assertRaises(TypeError, self.thetype, [[]])
|
---|
59 |
|
---|
60 | def test_len(self):
|
---|
61 | self.assertEqual(len(self.s), len(self.d))
|
---|
62 |
|
---|
63 | def test_contains(self):
|
---|
64 | for c in self.letters:
|
---|
65 | self.assertEqual(c in self.s, c in self.d)
|
---|
66 | self.assertRaises(TypeError, self.s.__contains__, [[]])
|
---|
67 | s = self.thetype([frozenset(self.letters)])
|
---|
68 | self.assertIn(self.thetype(self.letters), s)
|
---|
69 |
|
---|
70 | def test_union(self):
|
---|
71 | u = self.s.union(self.otherword)
|
---|
72 | for c in self.letters:
|
---|
73 | self.assertEqual(c in u, c in self.d or c in self.otherword)
|
---|
74 | self.assertEqual(self.s, self.thetype(self.word))
|
---|
75 | self.assertEqual(type(u), self.thetype)
|
---|
76 | self.assertRaises(PassThru, self.s.union, check_pass_thru())
|
---|
77 | self.assertRaises(TypeError, self.s.union, [[]])
|
---|
78 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
79 | self.assertEqual(self.thetype('abcba').union(C('cdc')), set('abcd'))
|
---|
80 | self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg'))
|
---|
81 | self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc'))
|
---|
82 | self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef'))
|
---|
83 | self.assertEqual(self.thetype('abcba').union(C('ef'), C('fg')), set('abcefg'))
|
---|
84 |
|
---|
85 | # Issue #6573
|
---|
86 | x = self.thetype()
|
---|
87 | self.assertEqual(x.union(set([1]), x, set([2])), self.thetype([1, 2]))
|
---|
88 |
|
---|
89 | def test_or(self):
|
---|
90 | i = self.s.union(self.otherword)
|
---|
91 | self.assertEqual(self.s | set(self.otherword), i)
|
---|
92 | self.assertEqual(self.s | frozenset(self.otherword), i)
|
---|
93 | try:
|
---|
94 | self.s | self.otherword
|
---|
95 | except TypeError:
|
---|
96 | pass
|
---|
97 | else:
|
---|
98 | self.fail("s|t did not screen-out general iterables")
|
---|
99 |
|
---|
100 | def test_intersection(self):
|
---|
101 | i = self.s.intersection(self.otherword)
|
---|
102 | for c in self.letters:
|
---|
103 | self.assertEqual(c in i, c in self.d and c in self.otherword)
|
---|
104 | self.assertEqual(self.s, self.thetype(self.word))
|
---|
105 | self.assertEqual(type(i), self.thetype)
|
---|
106 | self.assertRaises(PassThru, self.s.intersection, check_pass_thru())
|
---|
107 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
108 | self.assertEqual(self.thetype('abcba').intersection(C('cdc')), set('cc'))
|
---|
109 | self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set(''))
|
---|
110 | self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
|
---|
111 | self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
|
---|
112 | self.assertEqual(self.thetype('abcba').intersection(C('cbcf'), C('bag')), set('b'))
|
---|
113 | s = self.thetype('abcba')
|
---|
114 | z = s.intersection()
|
---|
115 | if self.thetype == frozenset():
|
---|
116 | self.assertEqual(id(s), id(z))
|
---|
117 | else:
|
---|
118 | self.assertNotEqual(id(s), id(z))
|
---|
119 |
|
---|
120 | def test_isdisjoint(self):
|
---|
121 | def f(s1, s2):
|
---|
122 | 'Pure python equivalent of isdisjoint()'
|
---|
123 | return not set(s1).intersection(s2)
|
---|
124 | for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
|
---|
125 | s1 = self.thetype(larg)
|
---|
126 | for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
|
---|
127 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
128 | s2 = C(rarg)
|
---|
129 | actual = s1.isdisjoint(s2)
|
---|
130 | expected = f(s1, s2)
|
---|
131 | self.assertEqual(actual, expected)
|
---|
132 | self.assertTrue(actual is True or actual is False)
|
---|
133 |
|
---|
134 | def test_and(self):
|
---|
135 | i = self.s.intersection(self.otherword)
|
---|
136 | self.assertEqual(self.s & set(self.otherword), i)
|
---|
137 | self.assertEqual(self.s & frozenset(self.otherword), i)
|
---|
138 | try:
|
---|
139 | self.s & self.otherword
|
---|
140 | except TypeError:
|
---|
141 | pass
|
---|
142 | else:
|
---|
143 | self.fail("s&t did not screen-out general iterables")
|
---|
144 |
|
---|
145 | def test_difference(self):
|
---|
146 | i = self.s.difference(self.otherword)
|
---|
147 | for c in self.letters:
|
---|
148 | self.assertEqual(c in i, c in self.d and c not in self.otherword)
|
---|
149 | self.assertEqual(self.s, self.thetype(self.word))
|
---|
150 | self.assertEqual(type(i), self.thetype)
|
---|
151 | self.assertRaises(PassThru, self.s.difference, check_pass_thru())
|
---|
152 | self.assertRaises(TypeError, self.s.difference, [[]])
|
---|
153 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
154 | self.assertEqual(self.thetype('abcba').difference(C('cdc')), set('ab'))
|
---|
155 | self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc'))
|
---|
156 | self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a'))
|
---|
157 | self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc'))
|
---|
158 | self.assertEqual(self.thetype('abcba').difference(), set('abc'))
|
---|
159 | self.assertEqual(self.thetype('abcba').difference(C('a'), C('b')), set('c'))
|
---|
160 |
|
---|
161 | def test_sub(self):
|
---|
162 | i = self.s.difference(self.otherword)
|
---|
163 | self.assertEqual(self.s - set(self.otherword), i)
|
---|
164 | self.assertEqual(self.s - frozenset(self.otherword), i)
|
---|
165 | try:
|
---|
166 | self.s - self.otherword
|
---|
167 | except TypeError:
|
---|
168 | pass
|
---|
169 | else:
|
---|
170 | self.fail("s-t did not screen-out general iterables")
|
---|
171 |
|
---|
172 | def test_symmetric_difference(self):
|
---|
173 | i = self.s.symmetric_difference(self.otherword)
|
---|
174 | for c in self.letters:
|
---|
175 | self.assertEqual(c in i, (c in self.d) ^ (c in self.otherword))
|
---|
176 | self.assertEqual(self.s, self.thetype(self.word))
|
---|
177 | self.assertEqual(type(i), self.thetype)
|
---|
178 | self.assertRaises(PassThru, self.s.symmetric_difference, check_pass_thru())
|
---|
179 | self.assertRaises(TypeError, self.s.symmetric_difference, [[]])
|
---|
180 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
181 | self.assertEqual(self.thetype('abcba').symmetric_difference(C('cdc')), set('abd'))
|
---|
182 | self.assertEqual(self.thetype('abcba').symmetric_difference(C('efgfe')), set('abcefg'))
|
---|
183 | self.assertEqual(self.thetype('abcba').symmetric_difference(C('ccb')), set('a'))
|
---|
184 | self.assertEqual(self.thetype('abcba').symmetric_difference(C('ef')), set('abcef'))
|
---|
185 |
|
---|
186 | def test_xor(self):
|
---|
187 | i = self.s.symmetric_difference(self.otherword)
|
---|
188 | self.assertEqual(self.s ^ set(self.otherword), i)
|
---|
189 | self.assertEqual(self.s ^ frozenset(self.otherword), i)
|
---|
190 | try:
|
---|
191 | self.s ^ self.otherword
|
---|
192 | except TypeError:
|
---|
193 | pass
|
---|
194 | else:
|
---|
195 | self.fail("s^t did not screen-out general iterables")
|
---|
196 |
|
---|
197 | def test_equality(self):
|
---|
198 | self.assertEqual(self.s, set(self.word))
|
---|
199 | self.assertEqual(self.s, frozenset(self.word))
|
---|
200 | self.assertEqual(self.s == self.word, False)
|
---|
201 | self.assertNotEqual(self.s, set(self.otherword))
|
---|
202 | self.assertNotEqual(self.s, frozenset(self.otherword))
|
---|
203 | self.assertEqual(self.s != self.word, True)
|
---|
204 |
|
---|
205 | def test_setOfFrozensets(self):
|
---|
206 | t = map(frozenset, ['abcdef', 'bcd', 'bdcb', 'fed', 'fedccba'])
|
---|
207 | s = self.thetype(t)
|
---|
208 | self.assertEqual(len(s), 3)
|
---|
209 |
|
---|
210 | def test_compare(self):
|
---|
211 | self.assertRaises(TypeError, self.s.__cmp__, self.s)
|
---|
212 |
|
---|
213 | def test_sub_and_super(self):
|
---|
214 | p, q, r = map(self.thetype, ['ab', 'abcde', 'def'])
|
---|
215 | self.assertTrue(p < q)
|
---|
216 | self.assertTrue(p <= q)
|
---|
217 | self.assertTrue(q <= q)
|
---|
218 | self.assertTrue(q > p)
|
---|
219 | self.assertTrue(q >= p)
|
---|
220 | self.assertFalse(q < r)
|
---|
221 | self.assertFalse(q <= r)
|
---|
222 | self.assertFalse(q > r)
|
---|
223 | self.assertFalse(q >= r)
|
---|
224 | self.assertTrue(set('a').issubset('abc'))
|
---|
225 | self.assertTrue(set('abc').issuperset('a'))
|
---|
226 | self.assertFalse(set('a').issubset('cbs'))
|
---|
227 | self.assertFalse(set('cbs').issuperset('a'))
|
---|
228 |
|
---|
229 | def test_pickling(self):
|
---|
230 | for i in range(pickle.HIGHEST_PROTOCOL + 1):
|
---|
231 | p = pickle.dumps(self.s, i)
|
---|
232 | dup = pickle.loads(p)
|
---|
233 | self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup))
|
---|
234 | if type(self.s) not in (set, frozenset):
|
---|
235 | self.s.x = 10
|
---|
236 | p = pickle.dumps(self.s)
|
---|
237 | dup = pickle.loads(p)
|
---|
238 | self.assertEqual(self.s.x, dup.x)
|
---|
239 |
|
---|
240 | def test_deepcopy(self):
|
---|
241 | class Tracer:
|
---|
242 | def __init__(self, value):
|
---|
243 | self.value = value
|
---|
244 | def __hash__(self):
|
---|
245 | return self.value
|
---|
246 | def __deepcopy__(self, memo=None):
|
---|
247 | return Tracer(self.value + 1)
|
---|
248 | t = Tracer(10)
|
---|
249 | s = self.thetype([t])
|
---|
250 | dup = copy.deepcopy(s)
|
---|
251 | self.assertNotEqual(id(s), id(dup))
|
---|
252 | for elem in dup:
|
---|
253 | newt = elem
|
---|
254 | self.assertNotEqual(id(t), id(newt))
|
---|
255 | self.assertEqual(t.value + 1, newt.value)
|
---|
256 |
|
---|
257 | def test_gc(self):
|
---|
258 | # Create a nest of cycles to exercise overall ref count check
|
---|
259 | class A:
|
---|
260 | pass
|
---|
261 | s = set(A() for i in xrange(1000))
|
---|
262 | for elem in s:
|
---|
263 | elem.cycle = s
|
---|
264 | elem.sub = elem
|
---|
265 | elem.set = set([elem])
|
---|
266 |
|
---|
267 | def test_subclass_with_custom_hash(self):
|
---|
268 | # Bug #1257731
|
---|
269 | class H(self.thetype):
|
---|
270 | def __hash__(self):
|
---|
271 | return int(id(self) & 0x7fffffff)
|
---|
272 | s=H()
|
---|
273 | f=set()
|
---|
274 | f.add(s)
|
---|
275 | self.assertIn(s, f)
|
---|
276 | f.remove(s)
|
---|
277 | f.add(s)
|
---|
278 | f.discard(s)
|
---|
279 |
|
---|
280 | def test_badcmp(self):
|
---|
281 | s = self.thetype([BadCmp()])
|
---|
282 | # Detect comparison errors during insertion and lookup
|
---|
283 | self.assertRaises(RuntimeError, self.thetype, [BadCmp(), BadCmp()])
|
---|
284 | self.assertRaises(RuntimeError, s.__contains__, BadCmp())
|
---|
285 | # Detect errors during mutating operations
|
---|
286 | if hasattr(s, 'add'):
|
---|
287 | self.assertRaises(RuntimeError, s.add, BadCmp())
|
---|
288 | self.assertRaises(RuntimeError, s.discard, BadCmp())
|
---|
289 | self.assertRaises(RuntimeError, s.remove, BadCmp())
|
---|
290 |
|
---|
291 | def test_cyclical_repr(self):
|
---|
292 | w = ReprWrapper()
|
---|
293 | s = self.thetype([w])
|
---|
294 | w.value = s
|
---|
295 | name = repr(s).partition('(')[0] # strip class name from repr string
|
---|
296 | self.assertEqual(repr(s), '%s([%s(...)])' % (name, name))
|
---|
297 |
|
---|
298 | def test_cyclical_print(self):
|
---|
299 | w = ReprWrapper()
|
---|
300 | s = self.thetype([w])
|
---|
301 | w.value = s
|
---|
302 | fo = open(test_support.TESTFN, "wb")
|
---|
303 | try:
|
---|
304 | print >> fo, s,
|
---|
305 | fo.close()
|
---|
306 | fo = open(test_support.TESTFN, "rb")
|
---|
307 | self.assertEqual(fo.read(), repr(s))
|
---|
308 | finally:
|
---|
309 | fo.close()
|
---|
310 | test_support.unlink(test_support.TESTFN)
|
---|
311 |
|
---|
312 | def test_do_not_rehash_dict_keys(self):
|
---|
313 | n = 10
|
---|
314 | d = dict.fromkeys(map(HashCountingInt, xrange(n)))
|
---|
315 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
316 | s = self.thetype(d)
|
---|
317 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
318 | s.difference(d)
|
---|
319 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
320 | if hasattr(s, 'symmetric_difference_update'):
|
---|
321 | s.symmetric_difference_update(d)
|
---|
322 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
323 | d2 = dict.fromkeys(set(d))
|
---|
324 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
325 | d3 = dict.fromkeys(frozenset(d))
|
---|
326 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
327 | d3 = dict.fromkeys(frozenset(d), 123)
|
---|
328 | self.assertEqual(sum(elem.hash_count for elem in d), n)
|
---|
329 | self.assertEqual(d3, dict.fromkeys(d, 123))
|
---|
330 |
|
---|
331 | def test_container_iterator(self):
|
---|
332 | # Bug #3680: tp_traverse was not implemented for set iterator object
|
---|
333 | class C(object):
|
---|
334 | pass
|
---|
335 | obj = C()
|
---|
336 | ref = weakref.ref(obj)
|
---|
337 | container = set([obj, 1])
|
---|
338 | obj.x = iter(container)
|
---|
339 | del obj, container
|
---|
340 | gc.collect()
|
---|
341 | self.assertTrue(ref() is None, "Cycle was not collected")
|
---|
342 |
|
---|
343 | class TestSet(TestJointOps):
|
---|
344 | thetype = set
|
---|
345 |
|
---|
346 | def test_init(self):
|
---|
347 | s = self.thetype()
|
---|
348 | s.__init__(self.word)
|
---|
349 | self.assertEqual(s, set(self.word))
|
---|
350 | s.__init__(self.otherword)
|
---|
351 | self.assertEqual(s, set(self.otherword))
|
---|
352 | self.assertRaises(TypeError, s.__init__, s, 2);
|
---|
353 | self.assertRaises(TypeError, s.__init__, 1);
|
---|
354 |
|
---|
355 | def test_constructor_identity(self):
|
---|
356 | s = self.thetype(range(3))
|
---|
357 | t = self.thetype(s)
|
---|
358 | self.assertNotEqual(id(s), id(t))
|
---|
359 |
|
---|
360 | def test_hash(self):
|
---|
361 | self.assertRaises(TypeError, hash, self.s)
|
---|
362 |
|
---|
363 | def test_clear(self):
|
---|
364 | self.s.clear()
|
---|
365 | self.assertEqual(self.s, set())
|
---|
366 | self.assertEqual(len(self.s), 0)
|
---|
367 |
|
---|
368 | def test_copy(self):
|
---|
369 | dup = self.s.copy()
|
---|
370 | self.assertEqual(self.s, dup)
|
---|
371 | self.assertNotEqual(id(self.s), id(dup))
|
---|
372 |
|
---|
373 | def test_add(self):
|
---|
374 | self.s.add('Q')
|
---|
375 | self.assertIn('Q', self.s)
|
---|
376 | dup = self.s.copy()
|
---|
377 | self.s.add('Q')
|
---|
378 | self.assertEqual(self.s, dup)
|
---|
379 | self.assertRaises(TypeError, self.s.add, [])
|
---|
380 |
|
---|
381 | def test_remove(self):
|
---|
382 | self.s.remove('a')
|
---|
383 | self.assertNotIn('a', self.s)
|
---|
384 | self.assertRaises(KeyError, self.s.remove, 'Q')
|
---|
385 | self.assertRaises(TypeError, self.s.remove, [])
|
---|
386 | s = self.thetype([frozenset(self.word)])
|
---|
387 | self.assertIn(self.thetype(self.word), s)
|
---|
388 | s.remove(self.thetype(self.word))
|
---|
389 | self.assertNotIn(self.thetype(self.word), s)
|
---|
390 | self.assertRaises(KeyError, self.s.remove, self.thetype(self.word))
|
---|
391 |
|
---|
392 | def test_remove_keyerror_unpacking(self):
|
---|
393 | # bug: www.python.org/sf/1576657
|
---|
394 | for v1 in ['Q', (1,)]:
|
---|
395 | try:
|
---|
396 | self.s.remove(v1)
|
---|
397 | except KeyError, e:
|
---|
398 | v2 = e.args[0]
|
---|
399 | self.assertEqual(v1, v2)
|
---|
400 | else:
|
---|
401 | self.fail()
|
---|
402 |
|
---|
403 | def test_remove_keyerror_set(self):
|
---|
404 | key = self.thetype([3, 4])
|
---|
405 | try:
|
---|
406 | self.s.remove(key)
|
---|
407 | except KeyError as e:
|
---|
408 | self.assertTrue(e.args[0] is key,
|
---|
409 | "KeyError should be {0}, not {1}".format(key,
|
---|
410 | e.args[0]))
|
---|
411 | else:
|
---|
412 | self.fail()
|
---|
413 |
|
---|
414 | def test_discard(self):
|
---|
415 | self.s.discard('a')
|
---|
416 | self.assertNotIn('a', self.s)
|
---|
417 | self.s.discard('Q')
|
---|
418 | self.assertRaises(TypeError, self.s.discard, [])
|
---|
419 | s = self.thetype([frozenset(self.word)])
|
---|
420 | self.assertIn(self.thetype(self.word), s)
|
---|
421 | s.discard(self.thetype(self.word))
|
---|
422 | self.assertNotIn(self.thetype(self.word), s)
|
---|
423 | s.discard(self.thetype(self.word))
|
---|
424 |
|
---|
425 | def test_pop(self):
|
---|
426 | for i in xrange(len(self.s)):
|
---|
427 | elem = self.s.pop()
|
---|
428 | self.assertNotIn(elem, self.s)
|
---|
429 | self.assertRaises(KeyError, self.s.pop)
|
---|
430 |
|
---|
431 | def test_update(self):
|
---|
432 | retval = self.s.update(self.otherword)
|
---|
433 | self.assertEqual(retval, None)
|
---|
434 | for c in (self.word + self.otherword):
|
---|
435 | self.assertIn(c, self.s)
|
---|
436 | self.assertRaises(PassThru, self.s.update, check_pass_thru())
|
---|
437 | self.assertRaises(TypeError, self.s.update, [[]])
|
---|
438 | for p, q in (('cdc', 'abcd'), ('efgfe', 'abcefg'), ('ccb', 'abc'), ('ef', 'abcef')):
|
---|
439 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
440 | s = self.thetype('abcba')
|
---|
441 | self.assertEqual(s.update(C(p)), None)
|
---|
442 | self.assertEqual(s, set(q))
|
---|
443 | for p in ('cdc', 'efgfe', 'ccb', 'ef', 'abcda'):
|
---|
444 | q = 'ahi'
|
---|
445 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
446 | s = self.thetype('abcba')
|
---|
447 | self.assertEqual(s.update(C(p), C(q)), None)
|
---|
448 | self.assertEqual(s, set(s) | set(p) | set(q))
|
---|
449 |
|
---|
450 | def test_ior(self):
|
---|
451 | self.s |= set(self.otherword)
|
---|
452 | for c in (self.word + self.otherword):
|
---|
453 | self.assertIn(c, self.s)
|
---|
454 |
|
---|
455 | def test_intersection_update(self):
|
---|
456 | retval = self.s.intersection_update(self.otherword)
|
---|
457 | self.assertEqual(retval, None)
|
---|
458 | for c in (self.word + self.otherword):
|
---|
459 | if c in self.otherword and c in self.word:
|
---|
460 | self.assertIn(c, self.s)
|
---|
461 | else:
|
---|
462 | self.assertNotIn(c, self.s)
|
---|
463 | self.assertRaises(PassThru, self.s.intersection_update, check_pass_thru())
|
---|
464 | self.assertRaises(TypeError, self.s.intersection_update, [[]])
|
---|
465 | for p, q in (('cdc', 'c'), ('efgfe', ''), ('ccb', 'bc'), ('ef', '')):
|
---|
466 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
467 | s = self.thetype('abcba')
|
---|
468 | self.assertEqual(s.intersection_update(C(p)), None)
|
---|
469 | self.assertEqual(s, set(q))
|
---|
470 | ss = 'abcba'
|
---|
471 | s = self.thetype(ss)
|
---|
472 | t = 'cbc'
|
---|
473 | self.assertEqual(s.intersection_update(C(p), C(t)), None)
|
---|
474 | self.assertEqual(s, set('abcba')&set(p)&set(t))
|
---|
475 |
|
---|
476 | def test_iand(self):
|
---|
477 | self.s &= set(self.otherword)
|
---|
478 | for c in (self.word + self.otherword):
|
---|
479 | if c in self.otherword and c in self.word:
|
---|
480 | self.assertIn(c, self.s)
|
---|
481 | else:
|
---|
482 | self.assertNotIn(c, self.s)
|
---|
483 |
|
---|
484 | def test_difference_update(self):
|
---|
485 | retval = self.s.difference_update(self.otherword)
|
---|
486 | self.assertEqual(retval, None)
|
---|
487 | for c in (self.word + self.otherword):
|
---|
488 | if c in self.word and c not in self.otherword:
|
---|
489 | self.assertIn(c, self.s)
|
---|
490 | else:
|
---|
491 | self.assertNotIn(c, self.s)
|
---|
492 | self.assertRaises(PassThru, self.s.difference_update, check_pass_thru())
|
---|
493 | self.assertRaises(TypeError, self.s.difference_update, [[]])
|
---|
494 | self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
|
---|
495 | for p, q in (('cdc', 'ab'), ('efgfe', 'abc'), ('ccb', 'a'), ('ef', 'abc')):
|
---|
496 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
497 | s = self.thetype('abcba')
|
---|
498 | self.assertEqual(s.difference_update(C(p)), None)
|
---|
499 | self.assertEqual(s, set(q))
|
---|
500 |
|
---|
501 | s = self.thetype('abcdefghih')
|
---|
502 | s.difference_update()
|
---|
503 | self.assertEqual(s, self.thetype('abcdefghih'))
|
---|
504 |
|
---|
505 | s = self.thetype('abcdefghih')
|
---|
506 | s.difference_update(C('aba'))
|
---|
507 | self.assertEqual(s, self.thetype('cdefghih'))
|
---|
508 |
|
---|
509 | s = self.thetype('abcdefghih')
|
---|
510 | s.difference_update(C('cdc'), C('aba'))
|
---|
511 | self.assertEqual(s, self.thetype('efghih'))
|
---|
512 |
|
---|
513 | def test_isub(self):
|
---|
514 | self.s -= set(self.otherword)
|
---|
515 | for c in (self.word + self.otherword):
|
---|
516 | if c in self.word and c not in self.otherword:
|
---|
517 | self.assertIn(c, self.s)
|
---|
518 | else:
|
---|
519 | self.assertNotIn(c, self.s)
|
---|
520 |
|
---|
521 | def test_symmetric_difference_update(self):
|
---|
522 | retval = self.s.symmetric_difference_update(self.otherword)
|
---|
523 | self.assertEqual(retval, None)
|
---|
524 | for c in (self.word + self.otherword):
|
---|
525 | if (c in self.word) ^ (c in self.otherword):
|
---|
526 | self.assertIn(c, self.s)
|
---|
527 | else:
|
---|
528 | self.assertNotIn(c, self.s)
|
---|
529 | self.assertRaises(PassThru, self.s.symmetric_difference_update, check_pass_thru())
|
---|
530 | self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
|
---|
531 | for p, q in (('cdc', 'abd'), ('efgfe', 'abcefg'), ('ccb', 'a'), ('ef', 'abcef')):
|
---|
532 | for C in set, frozenset, dict.fromkeys, str, unicode, list, tuple:
|
---|
533 | s = self.thetype('abcba')
|
---|
534 | self.assertEqual(s.symmetric_difference_update(C(p)), None)
|
---|
535 | self.assertEqual(s, set(q))
|
---|
536 |
|
---|
537 | def test_ixor(self):
|
---|
538 | self.s ^= set(self.otherword)
|
---|
539 | for c in (self.word + self.otherword):
|
---|
540 | if (c in self.word) ^ (c in self.otherword):
|
---|
541 | self.assertIn(c, self.s)
|
---|
542 | else:
|
---|
543 | self.assertNotIn(c, self.s)
|
---|
544 |
|
---|
545 | def test_inplace_on_self(self):
|
---|
546 | t = self.s.copy()
|
---|
547 | t |= t
|
---|
548 | self.assertEqual(t, self.s)
|
---|
549 | t &= t
|
---|
550 | self.assertEqual(t, self.s)
|
---|
551 | t -= t
|
---|
552 | self.assertEqual(t, self.thetype())
|
---|
553 | t = self.s.copy()
|
---|
554 | t ^= t
|
---|
555 | self.assertEqual(t, self.thetype())
|
---|
556 |
|
---|
557 | def test_weakref(self):
|
---|
558 | s = self.thetype('gallahad')
|
---|
559 | p = weakref.proxy(s)
|
---|
560 | self.assertEqual(str(p), str(s))
|
---|
561 | s = None
|
---|
562 | self.assertRaises(ReferenceError, str, p)
|
---|
563 |
|
---|
564 | # C API test only available in a debug build
|
---|
565 | if hasattr(set, "test_c_api"):
|
---|
566 | def test_c_api(self):
|
---|
567 | self.assertEqual(set().test_c_api(), True)
|
---|
568 |
|
---|
569 | class SetSubclass(set):
|
---|
570 | pass
|
---|
571 |
|
---|
572 | class TestSetSubclass(TestSet):
|
---|
573 | thetype = SetSubclass
|
---|
574 |
|
---|
575 | class SetSubclassWithKeywordArgs(set):
|
---|
576 | def __init__(self, iterable=[], newarg=None):
|
---|
577 | set.__init__(self, iterable)
|
---|
578 |
|
---|
579 | class TestSetSubclassWithKeywordArgs(TestSet):
|
---|
580 |
|
---|
581 | def test_keywords_in_subclass(self):
|
---|
582 | 'SF bug #1486663 -- this used to erroneously raise a TypeError'
|
---|
583 | SetSubclassWithKeywordArgs(newarg=1)
|
---|
584 |
|
---|
585 | class TestFrozenSet(TestJointOps):
|
---|
586 | thetype = frozenset
|
---|
587 |
|
---|
588 | def test_init(self):
|
---|
589 | s = self.thetype(self.word)
|
---|
590 | s.__init__(self.otherword)
|
---|
591 | self.assertEqual(s, set(self.word))
|
---|
592 |
|
---|
593 | def test_singleton_empty_frozenset(self):
|
---|
594 | f = frozenset()
|
---|
595 | efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
|
---|
596 | frozenset(), frozenset([]), frozenset(()), frozenset(''),
|
---|
597 | frozenset(xrange(0)), frozenset(frozenset()),
|
---|
598 | frozenset(f), f]
|
---|
599 | # All of the empty frozensets should have just one id()
|
---|
600 | self.assertEqual(len(set(map(id, efs))), 1)
|
---|
601 |
|
---|
602 | def test_constructor_identity(self):
|
---|
603 | s = self.thetype(range(3))
|
---|
604 | t = self.thetype(s)
|
---|
605 | self.assertEqual(id(s), id(t))
|
---|
606 |
|
---|
607 | def test_hash(self):
|
---|
608 | self.assertEqual(hash(self.thetype('abcdeb')),
|
---|
609 | hash(self.thetype('ebecda')))
|
---|
610 |
|
---|
611 | # make sure that all permutations give the same hash value
|
---|
612 | n = 100
|
---|
613 | seq = [randrange(n) for i in xrange(n)]
|
---|
614 | results = set()
|
---|
615 | for i in xrange(200):
|
---|
616 | shuffle(seq)
|
---|
617 | results.add(hash(self.thetype(seq)))
|
---|
618 | self.assertEqual(len(results), 1)
|
---|
619 |
|
---|
620 | def test_copy(self):
|
---|
621 | dup = self.s.copy()
|
---|
622 | self.assertEqual(id(self.s), id(dup))
|
---|
623 |
|
---|
624 | def test_frozen_as_dictkey(self):
|
---|
625 | seq = range(10) + list('abcdefg') + ['apple']
|
---|
626 | key1 = self.thetype(seq)
|
---|
627 | key2 = self.thetype(reversed(seq))
|
---|
628 | self.assertEqual(key1, key2)
|
---|
629 | self.assertNotEqual(id(key1), id(key2))
|
---|
630 | d = {}
|
---|
631 | d[key1] = 42
|
---|
632 | self.assertEqual(d[key2], 42)
|
---|
633 |
|
---|
634 | def test_hash_caching(self):
|
---|
635 | f = self.thetype('abcdcda')
|
---|
636 | self.assertEqual(hash(f), hash(f))
|
---|
637 |
|
---|
638 | def test_hash_effectiveness(self):
|
---|
639 | n = 13
|
---|
640 | hashvalues = set()
|
---|
641 | addhashvalue = hashvalues.add
|
---|
642 | elemmasks = [(i+1, 1<<i) for i in range(n)]
|
---|
643 | for i in xrange(2**n):
|
---|
644 | addhashvalue(hash(frozenset([e for e, m in elemmasks if m&i])))
|
---|
645 | self.assertEqual(len(hashvalues), 2**n)
|
---|
646 |
|
---|
647 | class FrozenSetSubclass(frozenset):
|
---|
648 | pass
|
---|
649 |
|
---|
650 | class TestFrozenSetSubclass(TestFrozenSet):
|
---|
651 | thetype = FrozenSetSubclass
|
---|
652 |
|
---|
653 | def test_constructor_identity(self):
|
---|
654 | s = self.thetype(range(3))
|
---|
655 | t = self.thetype(s)
|
---|
656 | self.assertNotEqual(id(s), id(t))
|
---|
657 |
|
---|
658 | def test_copy(self):
|
---|
659 | dup = self.s.copy()
|
---|
660 | self.assertNotEqual(id(self.s), id(dup))
|
---|
661 |
|
---|
662 | def test_nested_empty_constructor(self):
|
---|
663 | s = self.thetype()
|
---|
664 | t = self.thetype(s)
|
---|
665 | self.assertEqual(s, t)
|
---|
666 |
|
---|
667 | def test_singleton_empty_frozenset(self):
|
---|
668 | Frozenset = self.thetype
|
---|
669 | f = frozenset()
|
---|
670 | F = Frozenset()
|
---|
671 | efs = [Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
|
---|
672 | Frozenset(), Frozenset([]), Frozenset(()), Frozenset(''),
|
---|
673 | Frozenset(xrange(0)), Frozenset(Frozenset()),
|
---|
674 | Frozenset(frozenset()), f, F, Frozenset(f), Frozenset(F)]
|
---|
675 | # All empty frozenset subclass instances should have different ids
|
---|
676 | self.assertEqual(len(set(map(id, efs))), len(efs))
|
---|
677 |
|
---|
678 | # Tests taken from test_sets.py =============================================
|
---|
679 |
|
---|
680 | empty_set = set()
|
---|
681 |
|
---|
682 | #==============================================================================
|
---|
683 |
|
---|
684 | class TestBasicOps(unittest.TestCase):
|
---|
685 |
|
---|
686 | def test_repr(self):
|
---|
687 | if self.repr is not None:
|
---|
688 | self.assertEqual(repr(self.set), self.repr)
|
---|
689 |
|
---|
690 | def check_repr_against_values(self):
|
---|
691 | text = repr(self.set)
|
---|
692 | self.assertTrue(text.startswith('{'))
|
---|
693 | self.assertTrue(text.endswith('}'))
|
---|
694 |
|
---|
695 | result = text[1:-1].split(', ')
|
---|
696 | result.sort()
|
---|
697 | sorted_repr_values = [repr(value) for value in self.values]
|
---|
698 | sorted_repr_values.sort()
|
---|
699 | self.assertEqual(result, sorted_repr_values)
|
---|
700 |
|
---|
701 | def test_print(self):
|
---|
702 | fo = open(test_support.TESTFN, "wb")
|
---|
703 | try:
|
---|
704 | print >> fo, self.set,
|
---|
705 | fo.close()
|
---|
706 | fo = open(test_support.TESTFN, "rb")
|
---|
707 | self.assertEqual(fo.read(), repr(self.set))
|
---|
708 | finally:
|
---|
709 | fo.close()
|
---|
710 | test_support.unlink(test_support.TESTFN)
|
---|
711 |
|
---|
712 | def test_length(self):
|
---|
713 | self.assertEqual(len(self.set), self.length)
|
---|
714 |
|
---|
715 | def test_self_equality(self):
|
---|
716 | self.assertEqual(self.set, self.set)
|
---|
717 |
|
---|
718 | def test_equivalent_equality(self):
|
---|
719 | self.assertEqual(self.set, self.dup)
|
---|
720 |
|
---|
721 | def test_copy(self):
|
---|
722 | self.assertEqual(self.set.copy(), self.dup)
|
---|
723 |
|
---|
724 | def test_self_union(self):
|
---|
725 | result = self.set | self.set
|
---|
726 | self.assertEqual(result, self.dup)
|
---|
727 |
|
---|
728 | def test_empty_union(self):
|
---|
729 | result = self.set | empty_set
|
---|
730 | self.assertEqual(result, self.dup)
|
---|
731 |
|
---|
732 | def test_union_empty(self):
|
---|
733 | result = empty_set | self.set
|
---|
734 | self.assertEqual(result, self.dup)
|
---|
735 |
|
---|
736 | def test_self_intersection(self):
|
---|
737 | result = self.set & self.set
|
---|
738 | self.assertEqual(result, self.dup)
|
---|
739 |
|
---|
740 | def test_empty_intersection(self):
|
---|
741 | result = self.set & empty_set
|
---|
742 | self.assertEqual(result, empty_set)
|
---|
743 |
|
---|
744 | def test_intersection_empty(self):
|
---|
745 | result = empty_set & self.set
|
---|
746 | self.assertEqual(result, empty_set)
|
---|
747 |
|
---|
748 | def test_self_isdisjoint(self):
|
---|
749 | result = self.set.isdisjoint(self.set)
|
---|
750 | self.assertEqual(result, not self.set)
|
---|
751 |
|
---|
752 | def test_empty_isdisjoint(self):
|
---|
753 | result = self.set.isdisjoint(empty_set)
|
---|
754 | self.assertEqual(result, True)
|
---|
755 |
|
---|
756 | def test_isdisjoint_empty(self):
|
---|
757 | result = empty_set.isdisjoint(self.set)
|
---|
758 | self.assertEqual(result, True)
|
---|
759 |
|
---|
760 | def test_self_symmetric_difference(self):
|
---|
761 | result = self.set ^ self.set
|
---|
762 | self.assertEqual(result, empty_set)
|
---|
763 |
|
---|
764 | def test_empty_symmetric_difference(self):
|
---|
765 | result = self.set ^ empty_set
|
---|
766 | self.assertEqual(result, self.set)
|
---|
767 |
|
---|
768 | def test_self_difference(self):
|
---|
769 | result = self.set - self.set
|
---|
770 | self.assertEqual(result, empty_set)
|
---|
771 |
|
---|
772 | def test_empty_difference(self):
|
---|
773 | result = self.set - empty_set
|
---|
774 | self.assertEqual(result, self.dup)
|
---|
775 |
|
---|
776 | def test_empty_difference_rev(self):
|
---|
777 | result = empty_set - self.set
|
---|
778 | self.assertEqual(result, empty_set)
|
---|
779 |
|
---|
780 | def test_iteration(self):
|
---|
781 | for v in self.set:
|
---|
782 | self.assertIn(v, self.values)
|
---|
783 | setiter = iter(self.set)
|
---|
784 | # note: __length_hint__ is an internal undocumented API,
|
---|
785 | # don't rely on it in your own programs
|
---|
786 | self.assertEqual(setiter.__length_hint__(), len(self.set))
|
---|
787 |
|
---|
788 | def test_pickling(self):
|
---|
789 | p = pickle.dumps(self.set)
|
---|
790 | copy = pickle.loads(p)
|
---|
791 | self.assertEqual(self.set, copy,
|
---|
792 | "%s != %s" % (self.set, copy))
|
---|
793 |
|
---|
794 | #------------------------------------------------------------------------------
|
---|
795 |
|
---|
796 | class TestBasicOpsEmpty(TestBasicOps):
|
---|
797 | def setUp(self):
|
---|
798 | self.case = "empty set"
|
---|
799 | self.values = []
|
---|
800 | self.set = set(self.values)
|
---|
801 | self.dup = set(self.values)
|
---|
802 | self.length = 0
|
---|
803 | self.repr = "set([])"
|
---|
804 |
|
---|
805 | #------------------------------------------------------------------------------
|
---|
806 |
|
---|
807 | class TestBasicOpsSingleton(TestBasicOps):
|
---|
808 | def setUp(self):
|
---|
809 | self.case = "unit set (number)"
|
---|
810 | self.values = [3]
|
---|
811 | self.set = set(self.values)
|
---|
812 | self.dup = set(self.values)
|
---|
813 | self.length = 1
|
---|
814 | self.repr = "set([3])"
|
---|
815 |
|
---|
816 | def test_in(self):
|
---|
817 | self.assertIn(3, self.set)
|
---|
818 |
|
---|
819 | def test_not_in(self):
|
---|
820 | self.assertNotIn(2, self.set)
|
---|
821 |
|
---|
822 | #------------------------------------------------------------------------------
|
---|
823 |
|
---|
824 | class TestBasicOpsTuple(TestBasicOps):
|
---|
825 | def setUp(self):
|
---|
826 | self.case = "unit set (tuple)"
|
---|
827 | self.values = [(0, "zero")]
|
---|
828 | self.set = set(self.values)
|
---|
829 | self.dup = set(self.values)
|
---|
830 | self.length = 1
|
---|
831 | self.repr = "set([(0, 'zero')])"
|
---|
832 |
|
---|
833 | def test_in(self):
|
---|
834 | self.assertIn((0, "zero"), self.set)
|
---|
835 |
|
---|
836 | def test_not_in(self):
|
---|
837 | self.assertNotIn(9, self.set)
|
---|
838 |
|
---|
839 | #------------------------------------------------------------------------------
|
---|
840 |
|
---|
841 | class TestBasicOpsTriple(TestBasicOps):
|
---|
842 | def setUp(self):
|
---|
843 | self.case = "triple set"
|
---|
844 | self.values = [0, "zero", operator.add]
|
---|
845 | self.set = set(self.values)
|
---|
846 | self.dup = set(self.values)
|
---|
847 | self.length = 3
|
---|
848 | self.repr = None
|
---|
849 |
|
---|
850 | #------------------------------------------------------------------------------
|
---|
851 |
|
---|
852 | class TestBasicOpsString(TestBasicOps):
|
---|
853 | def setUp(self):
|
---|
854 | self.case = "string set"
|
---|
855 | self.values = ["a", "b", "c"]
|
---|
856 | self.set = set(self.values)
|
---|
857 | self.dup = set(self.values)
|
---|
858 | self.length = 3
|
---|
859 |
|
---|
860 | def test_repr(self):
|
---|
861 | self.check_repr_against_values()
|
---|
862 |
|
---|
863 | #------------------------------------------------------------------------------
|
---|
864 |
|
---|
865 | class TestBasicOpsUnicode(TestBasicOps):
|
---|
866 | def setUp(self):
|
---|
867 | self.case = "unicode set"
|
---|
868 | self.values = [u"a", u"b", u"c"]
|
---|
869 | self.set = set(self.values)
|
---|
870 | self.dup = set(self.values)
|
---|
871 | self.length = 3
|
---|
872 |
|
---|
873 | def test_repr(self):
|
---|
874 | self.check_repr_against_values()
|
---|
875 |
|
---|
876 | #------------------------------------------------------------------------------
|
---|
877 |
|
---|
878 | class TestBasicOpsMixedStringUnicode(TestBasicOps):
|
---|
879 | def setUp(self):
|
---|
880 | self.case = "string and bytes set"
|
---|
881 | self.values = ["a", "b", u"a", u"b"]
|
---|
882 | self.set = set(self.values)
|
---|
883 | self.dup = set(self.values)
|
---|
884 | self.length = 4
|
---|
885 |
|
---|
886 | def test_repr(self):
|
---|
887 | with test_support.check_warnings():
|
---|
888 | self.check_repr_against_values()
|
---|
889 |
|
---|
890 | #==============================================================================
|
---|
891 |
|
---|
892 | def baditer():
|
---|
893 | raise TypeError
|
---|
894 | yield True
|
---|
895 |
|
---|
896 | def gooditer():
|
---|
897 | yield True
|
---|
898 |
|
---|
899 | class TestExceptionPropagation(unittest.TestCase):
|
---|
900 | """SF 628246: Set constructor should not trap iterator TypeErrors"""
|
---|
901 |
|
---|
902 | def test_instanceWithException(self):
|
---|
903 | self.assertRaises(TypeError, set, baditer())
|
---|
904 |
|
---|
905 | def test_instancesWithoutException(self):
|
---|
906 | # All of these iterables should load without exception.
|
---|
907 | set([1,2,3])
|
---|
908 | set((1,2,3))
|
---|
909 | set({'one':1, 'two':2, 'three':3})
|
---|
910 | set(xrange(3))
|
---|
911 | set('abc')
|
---|
912 | set(gooditer())
|
---|
913 |
|
---|
914 | def test_changingSizeWhileIterating(self):
|
---|
915 | s = set([1,2,3])
|
---|
916 | try:
|
---|
917 | for i in s:
|
---|
918 | s.update([4])
|
---|
919 | except RuntimeError:
|
---|
920 | pass
|
---|
921 | else:
|
---|
922 | self.fail("no exception when changing size during iteration")
|
---|
923 |
|
---|
924 | #==============================================================================
|
---|
925 |
|
---|
926 | class TestSetOfSets(unittest.TestCase):
|
---|
927 | def test_constructor(self):
|
---|
928 | inner = frozenset([1])
|
---|
929 | outer = set([inner])
|
---|
930 | element = outer.pop()
|
---|
931 | self.assertEqual(type(element), frozenset)
|
---|
932 | outer.add(inner) # Rebuild set of sets with .add method
|
---|
933 | outer.remove(inner)
|
---|
934 | self.assertEqual(outer, set()) # Verify that remove worked
|
---|
935 | outer.discard(inner) # Absence of KeyError indicates working fine
|
---|
936 |
|
---|
937 | #==============================================================================
|
---|
938 |
|
---|
939 | class TestBinaryOps(unittest.TestCase):
|
---|
940 | def setUp(self):
|
---|
941 | self.set = set((2, 4, 6))
|
---|
942 |
|
---|
943 | def test_eq(self): # SF bug 643115
|
---|
944 | self.assertEqual(self.set, set({2:1,4:3,6:5}))
|
---|
945 |
|
---|
946 | def test_union_subset(self):
|
---|
947 | result = self.set | set([2])
|
---|
948 | self.assertEqual(result, set((2, 4, 6)))
|
---|
949 |
|
---|
950 | def test_union_superset(self):
|
---|
951 | result = self.set | set([2, 4, 6, 8])
|
---|
952 | self.assertEqual(result, set([2, 4, 6, 8]))
|
---|
953 |
|
---|
954 | def test_union_overlap(self):
|
---|
955 | result = self.set | set([3, 4, 5])
|
---|
956 | self.assertEqual(result, set([2, 3, 4, 5, 6]))
|
---|
957 |
|
---|
958 | def test_union_non_overlap(self):
|
---|
959 | result = self.set | set([8])
|
---|
960 | self.assertEqual(result, set([2, 4, 6, 8]))
|
---|
961 |
|
---|
962 | def test_intersection_subset(self):
|
---|
963 | result = self.set & set((2, 4))
|
---|
964 | self.assertEqual(result, set((2, 4)))
|
---|
965 |
|
---|
966 | def test_intersection_superset(self):
|
---|
967 | result = self.set & set([2, 4, 6, 8])
|
---|
968 | self.assertEqual(result, set([2, 4, 6]))
|
---|
969 |
|
---|
970 | def test_intersection_overlap(self):
|
---|
971 | result = self.set & set([3, 4, 5])
|
---|
972 | self.assertEqual(result, set([4]))
|
---|
973 |
|
---|
974 | def test_intersection_non_overlap(self):
|
---|
975 | result = self.set & set([8])
|
---|
976 | self.assertEqual(result, empty_set)
|
---|
977 |
|
---|
978 | def test_isdisjoint_subset(self):
|
---|
979 | result = self.set.isdisjoint(set((2, 4)))
|
---|
980 | self.assertEqual(result, False)
|
---|
981 |
|
---|
982 | def test_isdisjoint_superset(self):
|
---|
983 | result = self.set.isdisjoint(set([2, 4, 6, 8]))
|
---|
984 | self.assertEqual(result, False)
|
---|
985 |
|
---|
986 | def test_isdisjoint_overlap(self):
|
---|
987 | result = self.set.isdisjoint(set([3, 4, 5]))
|
---|
988 | self.assertEqual(result, False)
|
---|
989 |
|
---|
990 | def test_isdisjoint_non_overlap(self):
|
---|
991 | result = self.set.isdisjoint(set([8]))
|
---|
992 | self.assertEqual(result, True)
|
---|
993 |
|
---|
994 | def test_sym_difference_subset(self):
|
---|
995 | result = self.set ^ set((2, 4))
|
---|
996 | self.assertEqual(result, set([6]))
|
---|
997 |
|
---|
998 | def test_sym_difference_superset(self):
|
---|
999 | result = self.set ^ set((2, 4, 6, 8))
|
---|
1000 | self.assertEqual(result, set([8]))
|
---|
1001 |
|
---|
1002 | def test_sym_difference_overlap(self):
|
---|
1003 | result = self.set ^ set((3, 4, 5))
|
---|
1004 | self.assertEqual(result, set([2, 3, 5, 6]))
|
---|
1005 |
|
---|
1006 | def test_sym_difference_non_overlap(self):
|
---|
1007 | result = self.set ^ set([8])
|
---|
1008 | self.assertEqual(result, set([2, 4, 6, 8]))
|
---|
1009 |
|
---|
1010 | def test_cmp(self):
|
---|
1011 | a, b = set('a'), set('b')
|
---|
1012 | self.assertRaises(TypeError, cmp, a, b)
|
---|
1013 |
|
---|
1014 | # You can view this as a buglet: cmp(a, a) does not raise TypeError,
|
---|
1015 | # because __eq__ is tried before __cmp__, and a.__eq__(a) returns True,
|
---|
1016 | # which Python thinks is good enough to synthesize a cmp() result
|
---|
1017 | # without calling __cmp__.
|
---|
1018 | self.assertEqual(cmp(a, a), 0)
|
---|
1019 |
|
---|
1020 | self.assertRaises(TypeError, cmp, a, 12)
|
---|
1021 | self.assertRaises(TypeError, cmp, "abc", a)
|
---|
1022 |
|
---|
1023 | #==============================================================================
|
---|
1024 |
|
---|
1025 | class TestUpdateOps(unittest.TestCase):
|
---|
1026 | def setUp(self):
|
---|
1027 | self.set = set((2, 4, 6))
|
---|
1028 |
|
---|
1029 | def test_union_subset(self):
|
---|
1030 | self.set |= set([2])
|
---|
1031 | self.assertEqual(self.set, set((2, 4, 6)))
|
---|
1032 |
|
---|
1033 | def test_union_superset(self):
|
---|
1034 | self.set |= set([2, 4, 6, 8])
|
---|
1035 | self.assertEqual(self.set, set([2, 4, 6, 8]))
|
---|
1036 |
|
---|
1037 | def test_union_overlap(self):
|
---|
1038 | self.set |= set([3, 4, 5])
|
---|
1039 | self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
|
---|
1040 |
|
---|
1041 | def test_union_non_overlap(self):
|
---|
1042 | self.set |= set([8])
|
---|
1043 | self.assertEqual(self.set, set([2, 4, 6, 8]))
|
---|
1044 |
|
---|
1045 | def test_union_method_call(self):
|
---|
1046 | self.set.update(set([3, 4, 5]))
|
---|
1047 | self.assertEqual(self.set, set([2, 3, 4, 5, 6]))
|
---|
1048 |
|
---|
1049 | def test_intersection_subset(self):
|
---|
1050 | self.set &= set((2, 4))
|
---|
1051 | self.assertEqual(self.set, set((2, 4)))
|
---|
1052 |
|
---|
1053 | def test_intersection_superset(self):
|
---|
1054 | self.set &= set([2, 4, 6, 8])
|
---|
1055 | self.assertEqual(self.set, set([2, 4, 6]))
|
---|
1056 |
|
---|
1057 | def test_intersection_overlap(self):
|
---|
1058 | self.set &= set([3, 4, 5])
|
---|
1059 | self.assertEqual(self.set, set([4]))
|
---|
1060 |
|
---|
1061 | def test_intersection_non_overlap(self):
|
---|
1062 | self.set &= set([8])
|
---|
1063 | self.assertEqual(self.set, empty_set)
|
---|
1064 |
|
---|
1065 | def test_intersection_method_call(self):
|
---|
1066 | self.set.intersection_update(set([3, 4, 5]))
|
---|
1067 | self.assertEqual(self.set, set([4]))
|
---|
1068 |
|
---|
1069 | def test_sym_difference_subset(self):
|
---|
1070 | self.set ^= set((2, 4))
|
---|
1071 | self.assertEqual(self.set, set([6]))
|
---|
1072 |
|
---|
1073 | def test_sym_difference_superset(self):
|
---|
1074 | self.set ^= set((2, 4, 6, 8))
|
---|
1075 | self.assertEqual(self.set, set([8]))
|
---|
1076 |
|
---|
1077 | def test_sym_difference_overlap(self):
|
---|
1078 | self.set ^= set((3, 4, 5))
|
---|
1079 | self.assertEqual(self.set, set([2, 3, 5, 6]))
|
---|
1080 |
|
---|
1081 | def test_sym_difference_non_overlap(self):
|
---|
1082 | self.set ^= set([8])
|
---|
1083 | self.assertEqual(self.set, set([2, 4, 6, 8]))
|
---|
1084 |
|
---|
1085 | def test_sym_difference_method_call(self):
|
---|
1086 | self.set.symmetric_difference_update(set([3, 4, 5]))
|
---|
1087 | self.assertEqual(self.set, set([2, 3, 5, 6]))
|
---|
1088 |
|
---|
1089 | def test_difference_subset(self):
|
---|
1090 | self.set -= set((2, 4))
|
---|
1091 | self.assertEqual(self.set, set([6]))
|
---|
1092 |
|
---|
1093 | def test_difference_superset(self):
|
---|
1094 | self.set -= set((2, 4, 6, 8))
|
---|
1095 | self.assertEqual(self.set, set([]))
|
---|
1096 |
|
---|
1097 | def test_difference_overlap(self):
|
---|
1098 | self.set -= set((3, 4, 5))
|
---|
1099 | self.assertEqual(self.set, set([2, 6]))
|
---|
1100 |
|
---|
1101 | def test_difference_non_overlap(self):
|
---|
1102 | self.set -= set([8])
|
---|
1103 | self.assertEqual(self.set, set([2, 4, 6]))
|
---|
1104 |
|
---|
1105 | def test_difference_method_call(self):
|
---|
1106 | self.set.difference_update(set([3, 4, 5]))
|
---|
1107 | self.assertEqual(self.set, set([2, 6]))
|
---|
1108 |
|
---|
1109 | #==============================================================================
|
---|
1110 |
|
---|
1111 | class TestMutate(unittest.TestCase):
|
---|
1112 | def setUp(self):
|
---|
1113 | self.values = ["a", "b", "c"]
|
---|
1114 | self.set = set(self.values)
|
---|
1115 |
|
---|
1116 | def test_add_present(self):
|
---|
1117 | self.set.add("c")
|
---|
1118 | self.assertEqual(self.set, set("abc"))
|
---|
1119 |
|
---|
1120 | def test_add_absent(self):
|
---|
1121 | self.set.add("d")
|
---|
1122 | self.assertEqual(self.set, set("abcd"))
|
---|
1123 |
|
---|
1124 | def test_add_until_full(self):
|
---|
1125 | tmp = set()
|
---|
1126 | expected_len = 0
|
---|
1127 | for v in self.values:
|
---|
1128 | tmp.add(v)
|
---|
1129 | expected_len += 1
|
---|
1130 | self.assertEqual(len(tmp), expected_len)
|
---|
1131 | self.assertEqual(tmp, self.set)
|
---|
1132 |
|
---|
1133 | def test_remove_present(self):
|
---|
1134 | self.set.remove("b")
|
---|
1135 | self.assertEqual(self.set, set("ac"))
|
---|
1136 |
|
---|
1137 | def test_remove_absent(self):
|
---|
1138 | try:
|
---|
1139 | self.set.remove("d")
|
---|
1140 | self.fail("Removing missing element should have raised LookupError")
|
---|
1141 | except LookupError:
|
---|
1142 | pass
|
---|
1143 |
|
---|
1144 | def test_remove_until_empty(self):
|
---|
1145 | expected_len = len(self.set)
|
---|
1146 | for v in self.values:
|
---|
1147 | self.set.remove(v)
|
---|
1148 | expected_len -= 1
|
---|
1149 | self.assertEqual(len(self.set), expected_len)
|
---|
1150 |
|
---|
1151 | def test_discard_present(self):
|
---|
1152 | self.set.discard("c")
|
---|
1153 | self.assertEqual(self.set, set("ab"))
|
---|
1154 |
|
---|
1155 | def test_discard_absent(self):
|
---|
1156 | self.set.discard("d")
|
---|
1157 | self.assertEqual(self.set, set("abc"))
|
---|
1158 |
|
---|
1159 | def test_clear(self):
|
---|
1160 | self.set.clear()
|
---|
1161 | self.assertEqual(len(self.set), 0)
|
---|
1162 |
|
---|
1163 | def test_pop(self):
|
---|
1164 | popped = {}
|
---|
1165 | while self.set:
|
---|
1166 | popped[self.set.pop()] = None
|
---|
1167 | self.assertEqual(len(popped), len(self.values))
|
---|
1168 | for v in self.values:
|
---|
1169 | self.assertIn(v, popped)
|
---|
1170 |
|
---|
1171 | def test_update_empty_tuple(self):
|
---|
1172 | self.set.update(())
|
---|
1173 | self.assertEqual(self.set, set(self.values))
|
---|
1174 |
|
---|
1175 | def test_update_unit_tuple_overlap(self):
|
---|
1176 | self.set.update(("a",))
|
---|
1177 | self.assertEqual(self.set, set(self.values))
|
---|
1178 |
|
---|
1179 | def test_update_unit_tuple_non_overlap(self):
|
---|
1180 | self.set.update(("a", "z"))
|
---|
1181 | self.assertEqual(self.set, set(self.values + ["z"]))
|
---|
1182 |
|
---|
1183 | #==============================================================================
|
---|
1184 |
|
---|
1185 | class TestSubsets(unittest.TestCase):
|
---|
1186 |
|
---|
1187 | case2method = {"<=": "issubset",
|
---|
1188 | ">=": "issuperset",
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 | reverse = {"==": "==",
|
---|
1192 | "!=": "!=",
|
---|
1193 | "<": ">",
|
---|
1194 | ">": "<",
|
---|
1195 | "<=": ">=",
|
---|
1196 | ">=": "<=",
|
---|
1197 | }
|
---|
1198 |
|
---|
1199 | def test_issubset(self):
|
---|
1200 | x = self.left
|
---|
1201 | y = self.right
|
---|
1202 | for case in "!=", "==", "<", "<=", ">", ">=":
|
---|
1203 | expected = case in self.cases
|
---|
1204 | # Test the binary infix spelling.
|
---|
1205 | result = eval("x" + case + "y", locals())
|
---|
1206 | self.assertEqual(result, expected)
|
---|
1207 | # Test the "friendly" method-name spelling, if one exists.
|
---|
1208 | if case in TestSubsets.case2method:
|
---|
1209 | method = getattr(x, TestSubsets.case2method[case])
|
---|
1210 | result = method(y)
|
---|
1211 | self.assertEqual(result, expected)
|
---|
1212 |
|
---|
1213 | # Now do the same for the operands reversed.
|
---|
1214 | rcase = TestSubsets.reverse[case]
|
---|
1215 | result = eval("y" + rcase + "x", locals())
|
---|
1216 | self.assertEqual(result, expected)
|
---|
1217 | if rcase in TestSubsets.case2method:
|
---|
1218 | method = getattr(y, TestSubsets.case2method[rcase])
|
---|
1219 | result = method(x)
|
---|
1220 | self.assertEqual(result, expected)
|
---|
1221 | #------------------------------------------------------------------------------
|
---|
1222 |
|
---|
1223 | class TestSubsetEqualEmpty(TestSubsets):
|
---|
1224 | left = set()
|
---|
1225 | right = set()
|
---|
1226 | name = "both empty"
|
---|
1227 | cases = "==", "<=", ">="
|
---|
1228 |
|
---|
1229 | #------------------------------------------------------------------------------
|
---|
1230 |
|
---|
1231 | class TestSubsetEqualNonEmpty(TestSubsets):
|
---|
1232 | left = set([1, 2])
|
---|
1233 | right = set([1, 2])
|
---|
1234 | name = "equal pair"
|
---|
1235 | cases = "==", "<=", ">="
|
---|
1236 |
|
---|
1237 | #------------------------------------------------------------------------------
|
---|
1238 |
|
---|
1239 | class TestSubsetEmptyNonEmpty(TestSubsets):
|
---|
1240 | left = set()
|
---|
1241 | right = set([1, 2])
|
---|
1242 | name = "one empty, one non-empty"
|
---|
1243 | cases = "!=", "<", "<="
|
---|
1244 |
|
---|
1245 | #------------------------------------------------------------------------------
|
---|
1246 |
|
---|
1247 | class TestSubsetPartial(TestSubsets):
|
---|
1248 | left = set([1])
|
---|
1249 | right = set([1, 2])
|
---|
1250 | name = "one a non-empty proper subset of other"
|
---|
1251 | cases = "!=", "<", "<="
|
---|
1252 |
|
---|
1253 | #------------------------------------------------------------------------------
|
---|
1254 |
|
---|
1255 | class TestSubsetNonOverlap(TestSubsets):
|
---|
1256 | left = set([1])
|
---|
1257 | right = set([2])
|
---|
1258 | name = "neither empty, neither contains"
|
---|
1259 | cases = "!="
|
---|
1260 |
|
---|
1261 | #==============================================================================
|
---|
1262 |
|
---|
1263 | class TestOnlySetsInBinaryOps(unittest.TestCase):
|
---|
1264 |
|
---|
1265 | def test_eq_ne(self):
|
---|
1266 | # Unlike the others, this is testing that == and != *are* allowed.
|
---|
1267 | self.assertEqual(self.other == self.set, False)
|
---|
1268 | self.assertEqual(self.set == self.other, False)
|
---|
1269 | self.assertEqual(self.other != self.set, True)
|
---|
1270 | self.assertEqual(self.set != self.other, True)
|
---|
1271 |
|
---|
1272 | def test_ge_gt_le_lt(self):
|
---|
1273 | self.assertRaises(TypeError, lambda: self.set < self.other)
|
---|
1274 | self.assertRaises(TypeError, lambda: self.set <= self.other)
|
---|
1275 | self.assertRaises(TypeError, lambda: self.set > self.other)
|
---|
1276 | self.assertRaises(TypeError, lambda: self.set >= self.other)
|
---|
1277 |
|
---|
1278 | self.assertRaises(TypeError, lambda: self.other < self.set)
|
---|
1279 | self.assertRaises(TypeError, lambda: self.other <= self.set)
|
---|
1280 | self.assertRaises(TypeError, lambda: self.other > self.set)
|
---|
1281 | self.assertRaises(TypeError, lambda: self.other >= self.set)
|
---|
1282 |
|
---|
1283 | def test_update_operator(self):
|
---|
1284 | try:
|
---|
1285 | self.set |= self.other
|
---|
1286 | except TypeError:
|
---|
1287 | pass
|
---|
1288 | else:
|
---|
1289 | self.fail("expected TypeError")
|
---|
1290 |
|
---|
1291 | def test_update(self):
|
---|
1292 | if self.otherIsIterable:
|
---|
1293 | self.set.update(self.other)
|
---|
1294 | else:
|
---|
1295 | self.assertRaises(TypeError, self.set.update, self.other)
|
---|
1296 |
|
---|
1297 | def test_union(self):
|
---|
1298 | self.assertRaises(TypeError, lambda: self.set | self.other)
|
---|
1299 | self.assertRaises(TypeError, lambda: self.other | self.set)
|
---|
1300 | if self.otherIsIterable:
|
---|
1301 | self.set.union(self.other)
|
---|
1302 | else:
|
---|
1303 | self.assertRaises(TypeError, self.set.union, self.other)
|
---|
1304 |
|
---|
1305 | def test_intersection_update_operator(self):
|
---|
1306 | try:
|
---|
1307 | self.set &= self.other
|
---|
1308 | except TypeError:
|
---|
1309 | pass
|
---|
1310 | else:
|
---|
1311 | self.fail("expected TypeError")
|
---|
1312 |
|
---|
1313 | def test_intersection_update(self):
|
---|
1314 | if self.otherIsIterable:
|
---|
1315 | self.set.intersection_update(self.other)
|
---|
1316 | else:
|
---|
1317 | self.assertRaises(TypeError,
|
---|
1318 | self.set.intersection_update,
|
---|
1319 | self.other)
|
---|
1320 |
|
---|
1321 | def test_intersection(self):
|
---|
1322 | self.assertRaises(TypeError, lambda: self.set & self.other)
|
---|
1323 | self.assertRaises(TypeError, lambda: self.other & self.set)
|
---|
1324 | if self.otherIsIterable:
|
---|
1325 | self.set.intersection(self.other)
|
---|
1326 | else:
|
---|
1327 | self.assertRaises(TypeError, self.set.intersection, self.other)
|
---|
1328 |
|
---|
1329 | def test_sym_difference_update_operator(self):
|
---|
1330 | try:
|
---|
1331 | self.set ^= self.other
|
---|
1332 | except TypeError:
|
---|
1333 | pass
|
---|
1334 | else:
|
---|
1335 | self.fail("expected TypeError")
|
---|
1336 |
|
---|
1337 | def test_sym_difference_update(self):
|
---|
1338 | if self.otherIsIterable:
|
---|
1339 | self.set.symmetric_difference_update(self.other)
|
---|
1340 | else:
|
---|
1341 | self.assertRaises(TypeError,
|
---|
1342 | self.set.symmetric_difference_update,
|
---|
1343 | self.other)
|
---|
1344 |
|
---|
1345 | def test_sym_difference(self):
|
---|
1346 | self.assertRaises(TypeError, lambda: self.set ^ self.other)
|
---|
1347 | self.assertRaises(TypeError, lambda: self.other ^ self.set)
|
---|
1348 | if self.otherIsIterable:
|
---|
1349 | self.set.symmetric_difference(self.other)
|
---|
1350 | else:
|
---|
1351 | self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
|
---|
1352 |
|
---|
1353 | def test_difference_update_operator(self):
|
---|
1354 | try:
|
---|
1355 | self.set -= self.other
|
---|
1356 | except TypeError:
|
---|
1357 | pass
|
---|
1358 | else:
|
---|
1359 | self.fail("expected TypeError")
|
---|
1360 |
|
---|
1361 | def test_difference_update(self):
|
---|
1362 | if self.otherIsIterable:
|
---|
1363 | self.set.difference_update(self.other)
|
---|
1364 | else:
|
---|
1365 | self.assertRaises(TypeError,
|
---|
1366 | self.set.difference_update,
|
---|
1367 | self.other)
|
---|
1368 |
|
---|
1369 | def test_difference(self):
|
---|
1370 | self.assertRaises(TypeError, lambda: self.set - self.other)
|
---|
1371 | self.assertRaises(TypeError, lambda: self.other - self.set)
|
---|
1372 | if self.otherIsIterable:
|
---|
1373 | self.set.difference(self.other)
|
---|
1374 | else:
|
---|
1375 | self.assertRaises(TypeError, self.set.difference, self.other)
|
---|
1376 |
|
---|
1377 | #------------------------------------------------------------------------------
|
---|
1378 |
|
---|
1379 | class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
|
---|
1380 | def setUp(self):
|
---|
1381 | self.set = set((1, 2, 3))
|
---|
1382 | self.other = 19
|
---|
1383 | self.otherIsIterable = False
|
---|
1384 |
|
---|
1385 | #------------------------------------------------------------------------------
|
---|
1386 |
|
---|
1387 | class TestOnlySetsDict(TestOnlySetsInBinaryOps):
|
---|
1388 | def setUp(self):
|
---|
1389 | self.set = set((1, 2, 3))
|
---|
1390 | self.other = {1:2, 3:4}
|
---|
1391 | self.otherIsIterable = True
|
---|
1392 |
|
---|
1393 | #------------------------------------------------------------------------------
|
---|
1394 |
|
---|
1395 | class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
|
---|
1396 | def setUp(self):
|
---|
1397 | self.set = set((1, 2, 3))
|
---|
1398 | self.other = operator.add
|
---|
1399 | self.otherIsIterable = False
|
---|
1400 |
|
---|
1401 | def test_ge_gt_le_lt(self):
|
---|
1402 | with test_support.check_py3k_warnings():
|
---|
1403 | super(TestOnlySetsOperator, self).test_ge_gt_le_lt()
|
---|
1404 |
|
---|
1405 | #------------------------------------------------------------------------------
|
---|
1406 |
|
---|
1407 | class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
|
---|
1408 | def setUp(self):
|
---|
1409 | self.set = set((1, 2, 3))
|
---|
1410 | self.other = (2, 4, 6)
|
---|
1411 | self.otherIsIterable = True
|
---|
1412 |
|
---|
1413 | #------------------------------------------------------------------------------
|
---|
1414 |
|
---|
1415 | class TestOnlySetsString(TestOnlySetsInBinaryOps):
|
---|
1416 | def setUp(self):
|
---|
1417 | self.set = set((1, 2, 3))
|
---|
1418 | self.other = 'abc'
|
---|
1419 | self.otherIsIterable = True
|
---|
1420 |
|
---|
1421 | #------------------------------------------------------------------------------
|
---|
1422 |
|
---|
1423 | class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
|
---|
1424 | def setUp(self):
|
---|
1425 | def gen():
|
---|
1426 | for i in xrange(0, 10, 2):
|
---|
1427 | yield i
|
---|
1428 | self.set = set((1, 2, 3))
|
---|
1429 | self.other = gen()
|
---|
1430 | self.otherIsIterable = True
|
---|
1431 |
|
---|
1432 | #==============================================================================
|
---|
1433 |
|
---|
1434 | class TestCopying(unittest.TestCase):
|
---|
1435 |
|
---|
1436 | def test_copy(self):
|
---|
1437 | dup = list(self.set.copy())
|
---|
1438 | self.assertEqual(len(dup), len(self.set))
|
---|
1439 | for el in self.set:
|
---|
1440 | self.assertIn(el, dup)
|
---|
1441 | pos = dup.index(el)
|
---|
1442 | self.assertIs(el, dup.pop(pos))
|
---|
1443 | self.assertFalse(dup)
|
---|
1444 |
|
---|
1445 | def test_deep_copy(self):
|
---|
1446 | dup = copy.deepcopy(self.set)
|
---|
1447 | self.assertSetEqual(dup, self.set)
|
---|
1448 |
|
---|
1449 | #------------------------------------------------------------------------------
|
---|
1450 |
|
---|
1451 | class TestCopyingEmpty(TestCopying):
|
---|
1452 | def setUp(self):
|
---|
1453 | self.set = set()
|
---|
1454 |
|
---|
1455 | #------------------------------------------------------------------------------
|
---|
1456 |
|
---|
1457 | class TestCopyingSingleton(TestCopying):
|
---|
1458 | def setUp(self):
|
---|
1459 | self.set = set(["hello"])
|
---|
1460 |
|
---|
1461 | #------------------------------------------------------------------------------
|
---|
1462 |
|
---|
1463 | class TestCopyingTriple(TestCopying):
|
---|
1464 | def setUp(self):
|
---|
1465 | self.set = set(["zero", 0, None])
|
---|
1466 |
|
---|
1467 | #------------------------------------------------------------------------------
|
---|
1468 |
|
---|
1469 | class TestCopyingTuple(TestCopying):
|
---|
1470 | def setUp(self):
|
---|
1471 | self.set = set([(1, 2)])
|
---|
1472 |
|
---|
1473 | #------------------------------------------------------------------------------
|
---|
1474 |
|
---|
1475 | class TestCopyingNested(TestCopying):
|
---|
1476 | def setUp(self):
|
---|
1477 | self.set = set([((1, 2), (3, 4))])
|
---|
1478 |
|
---|
1479 | #==============================================================================
|
---|
1480 |
|
---|
1481 | class TestIdentities(unittest.TestCase):
|
---|
1482 | def setUp(self):
|
---|
1483 | self.a = set('abracadabra')
|
---|
1484 | self.b = set('alacazam')
|
---|
1485 |
|
---|
1486 | def test_binopsVsSubsets(self):
|
---|
1487 | a, b = self.a, self.b
|
---|
1488 | self.assertTrue(a - b < a)
|
---|
1489 | self.assertTrue(b - a < b)
|
---|
1490 | self.assertTrue(a & b < a)
|
---|
1491 | self.assertTrue(a & b < b)
|
---|
1492 | self.assertTrue(a | b > a)
|
---|
1493 | self.assertTrue(a | b > b)
|
---|
1494 | self.assertTrue(a ^ b < a | b)
|
---|
1495 |
|
---|
1496 | def test_commutativity(self):
|
---|
1497 | a, b = self.a, self.b
|
---|
1498 | self.assertEqual(a&b, b&a)
|
---|
1499 | self.assertEqual(a|b, b|a)
|
---|
1500 | self.assertEqual(a^b, b^a)
|
---|
1501 | if a != b:
|
---|
1502 | self.assertNotEqual(a-b, b-a)
|
---|
1503 |
|
---|
1504 | def test_summations(self):
|
---|
1505 | # check that sums of parts equal the whole
|
---|
1506 | a, b = self.a, self.b
|
---|
1507 | self.assertEqual((a-b)|(a&b)|(b-a), a|b)
|
---|
1508 | self.assertEqual((a&b)|(a^b), a|b)
|
---|
1509 | self.assertEqual(a|(b-a), a|b)
|
---|
1510 | self.assertEqual((a-b)|b, a|b)
|
---|
1511 | self.assertEqual((a-b)|(a&b), a)
|
---|
1512 | self.assertEqual((b-a)|(a&b), b)
|
---|
1513 | self.assertEqual((a-b)|(b-a), a^b)
|
---|
1514 |
|
---|
1515 | def test_exclusion(self):
|
---|
1516 | # check that inverse operations show non-overlap
|
---|
1517 | a, b, zero = self.a, self.b, set()
|
---|
1518 | self.assertEqual((a-b)&b, zero)
|
---|
1519 | self.assertEqual((b-a)&a, zero)
|
---|
1520 | self.assertEqual((a&b)&(a^b), zero)
|
---|
1521 |
|
---|
1522 | # Tests derived from test_itertools.py =======================================
|
---|
1523 |
|
---|
1524 | def R(seqn):
|
---|
1525 | 'Regular generator'
|
---|
1526 | for i in seqn:
|
---|
1527 | yield i
|
---|
1528 |
|
---|
1529 | class G:
|
---|
1530 | 'Sequence using __getitem__'
|
---|
1531 | def __init__(self, seqn):
|
---|
1532 | self.seqn = seqn
|
---|
1533 | def __getitem__(self, i):
|
---|
1534 | return self.seqn[i]
|
---|
1535 |
|
---|
1536 | class I:
|
---|
1537 | 'Sequence using iterator protocol'
|
---|
1538 | def __init__(self, seqn):
|
---|
1539 | self.seqn = seqn
|
---|
1540 | self.i = 0
|
---|
1541 | def __iter__(self):
|
---|
1542 | return self
|
---|
1543 | def next(self):
|
---|
1544 | if self.i >= len(self.seqn): raise StopIteration
|
---|
1545 | v = self.seqn[self.i]
|
---|
1546 | self.i += 1
|
---|
1547 | return v
|
---|
1548 |
|
---|
1549 | class Ig:
|
---|
1550 | 'Sequence using iterator protocol defined with a generator'
|
---|
1551 | def __init__(self, seqn):
|
---|
1552 | self.seqn = seqn
|
---|
1553 | self.i = 0
|
---|
1554 | def __iter__(self):
|
---|
1555 | for val in self.seqn:
|
---|
1556 | yield val
|
---|
1557 |
|
---|
1558 | class X:
|
---|
1559 | 'Missing __getitem__ and __iter__'
|
---|
1560 | def __init__(self, seqn):
|
---|
1561 | self.seqn = seqn
|
---|
1562 | self.i = 0
|
---|
1563 | def next(self):
|
---|
1564 | if self.i >= len(self.seqn): raise StopIteration
|
---|
1565 | v = self.seqn[self.i]
|
---|
1566 | self.i += 1
|
---|
1567 | return v
|
---|
1568 |
|
---|
1569 | class N:
|
---|
1570 | 'Iterator missing next()'
|
---|
1571 | def __init__(self, seqn):
|
---|
1572 | self.seqn = seqn
|
---|
1573 | self.i = 0
|
---|
1574 | def __iter__(self):
|
---|
1575 | return self
|
---|
1576 |
|
---|
1577 | class E:
|
---|
1578 | 'Test propagation of exceptions'
|
---|
1579 | def __init__(self, seqn):
|
---|
1580 | self.seqn = seqn
|
---|
1581 | self.i = 0
|
---|
1582 | def __iter__(self):
|
---|
1583 | return self
|
---|
1584 | def next(self):
|
---|
1585 | 3 // 0
|
---|
1586 |
|
---|
1587 | class S:
|
---|
1588 | 'Test immediate stop'
|
---|
1589 | def __init__(self, seqn):
|
---|
1590 | pass
|
---|
1591 | def __iter__(self):
|
---|
1592 | return self
|
---|
1593 | def next(self):
|
---|
1594 | raise StopIteration
|
---|
1595 |
|
---|
1596 | from itertools import chain, imap
|
---|
1597 | def L(seqn):
|
---|
1598 | 'Test multiple tiers of iterators'
|
---|
1599 | return chain(imap(lambda x:x, R(Ig(G(seqn)))))
|
---|
1600 |
|
---|
1601 | class TestVariousIteratorArgs(unittest.TestCase):
|
---|
1602 |
|
---|
1603 | def test_constructor(self):
|
---|
1604 | for cons in (set, frozenset):
|
---|
1605 | for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)):
|
---|
1606 | for g in (G, I, Ig, S, L, R):
|
---|
1607 | self.assertSetEqual(cons(g(s)), set(g(s)))
|
---|
1608 | self.assertRaises(TypeError, cons , X(s))
|
---|
1609 | self.assertRaises(TypeError, cons , N(s))
|
---|
1610 | self.assertRaises(ZeroDivisionError, cons , E(s))
|
---|
1611 |
|
---|
1612 | def test_inline_methods(self):
|
---|
1613 | s = set('november')
|
---|
1614 | for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
|
---|
1615 | for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint):
|
---|
1616 | for g in (G, I, Ig, L, R):
|
---|
1617 | expected = meth(data)
|
---|
1618 | actual = meth(G(data))
|
---|
1619 | if isinstance(expected, bool):
|
---|
1620 | self.assertEqual(actual, expected)
|
---|
1621 | else:
|
---|
1622 | self.assertSetEqual(actual, expected)
|
---|
1623 | self.assertRaises(TypeError, meth, X(s))
|
---|
1624 | self.assertRaises(TypeError, meth, N(s))
|
---|
1625 | self.assertRaises(ZeroDivisionError, meth, E(s))
|
---|
1626 |
|
---|
1627 | def test_inplace_methods(self):
|
---|
1628 | for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'):
|
---|
1629 | for methname in ('update', 'intersection_update',
|
---|
1630 | 'difference_update', 'symmetric_difference_update'):
|
---|
1631 | for g in (G, I, Ig, S, L, R):
|
---|
1632 | s = set('january')
|
---|
1633 | t = s.copy()
|
---|
1634 | getattr(s, methname)(list(g(data)))
|
---|
1635 | getattr(t, methname)(g(data))
|
---|
1636 | self.assertSetEqual(s, t)
|
---|
1637 |
|
---|
1638 | self.assertRaises(TypeError, getattr(set('january'), methname), X(data))
|
---|
1639 | self.assertRaises(TypeError, getattr(set('january'), methname), N(data))
|
---|
1640 | self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), E(data))
|
---|
1641 |
|
---|
1642 | class bad_eq:
|
---|
1643 | def __eq__(self, other):
|
---|
1644 | if be_bad:
|
---|
1645 | set2.clear()
|
---|
1646 | raise ZeroDivisionError
|
---|
1647 | return self is other
|
---|
1648 | def __hash__(self):
|
---|
1649 | return 0
|
---|
1650 |
|
---|
1651 | class bad_dict_clear:
|
---|
1652 | def __eq__(self, other):
|
---|
1653 | if be_bad:
|
---|
1654 | dict2.clear()
|
---|
1655 | return self is other
|
---|
1656 | def __hash__(self):
|
---|
1657 | return 0
|
---|
1658 |
|
---|
1659 | class TestWeirdBugs(unittest.TestCase):
|
---|
1660 | def test_8420_set_merge(self):
|
---|
1661 | # This used to segfault
|
---|
1662 | global be_bad, set2, dict2
|
---|
1663 | be_bad = False
|
---|
1664 | set1 = {bad_eq()}
|
---|
1665 | set2 = {bad_eq() for i in range(75)}
|
---|
1666 | be_bad = True
|
---|
1667 | self.assertRaises(ZeroDivisionError, set1.update, set2)
|
---|
1668 |
|
---|
1669 | be_bad = False
|
---|
1670 | set1 = {bad_dict_clear()}
|
---|
1671 | dict2 = {bad_dict_clear(): None}
|
---|
1672 | be_bad = True
|
---|
1673 | set1.symmetric_difference_update(dict2)
|
---|
1674 |
|
---|
1675 | # Application tests (based on David Eppstein's graph recipes ====================================
|
---|
1676 |
|
---|
1677 | def powerset(U):
|
---|
1678 | """Generates all subsets of a set or sequence U."""
|
---|
1679 | U = iter(U)
|
---|
1680 | try:
|
---|
1681 | x = frozenset([U.next()])
|
---|
1682 | for S in powerset(U):
|
---|
1683 | yield S
|
---|
1684 | yield S | x
|
---|
1685 | except StopIteration:
|
---|
1686 | yield frozenset()
|
---|
1687 |
|
---|
1688 | def cube(n):
|
---|
1689 | """Graph of n-dimensional hypercube."""
|
---|
1690 | singletons = [frozenset([x]) for x in range(n)]
|
---|
1691 | return dict([(x, frozenset([x^s for s in singletons]))
|
---|
1692 | for x in powerset(range(n))])
|
---|
1693 |
|
---|
1694 | def linegraph(G):
|
---|
1695 | """Graph, the vertices of which are edges of G,
|
---|
1696 | with two vertices being adjacent iff the corresponding
|
---|
1697 | edges share a vertex."""
|
---|
1698 | L = {}
|
---|
1699 | for x in G:
|
---|
1700 | for y in G[x]:
|
---|
1701 | nx = [frozenset([x,z]) for z in G[x] if z != y]
|
---|
1702 | ny = [frozenset([y,z]) for z in G[y] if z != x]
|
---|
1703 | L[frozenset([x,y])] = frozenset(nx+ny)
|
---|
1704 | return L
|
---|
1705 |
|
---|
1706 | def faces(G):
|
---|
1707 | 'Return a set of faces in G. Where a face is a set of vertices on that face'
|
---|
1708 | # currently limited to triangles,squares, and pentagons
|
---|
1709 | f = set()
|
---|
1710 | for v1, edges in G.items():
|
---|
1711 | for v2 in edges:
|
---|
1712 | for v3 in G[v2]:
|
---|
1713 | if v1 == v3:
|
---|
1714 | continue
|
---|
1715 | if v1 in G[v3]:
|
---|
1716 | f.add(frozenset([v1, v2, v3]))
|
---|
1717 | else:
|
---|
1718 | for v4 in G[v3]:
|
---|
1719 | if v4 == v2:
|
---|
1720 | continue
|
---|
1721 | if v1 in G[v4]:
|
---|
1722 | f.add(frozenset([v1, v2, v3, v4]))
|
---|
1723 | else:
|
---|
1724 | for v5 in G[v4]:
|
---|
1725 | if v5 == v3 or v5 == v2:
|
---|
1726 | continue
|
---|
1727 | if v1 in G[v5]:
|
---|
1728 | f.add(frozenset([v1, v2, v3, v4, v5]))
|
---|
1729 | return f
|
---|
1730 |
|
---|
1731 |
|
---|
1732 | class TestGraphs(unittest.TestCase):
|
---|
1733 |
|
---|
1734 | def test_cube(self):
|
---|
1735 |
|
---|
1736 | g = cube(3) # vert --> {v1, v2, v3}
|
---|
1737 | vertices1 = set(g)
|
---|
1738 | self.assertEqual(len(vertices1), 8) # eight vertices
|
---|
1739 | for edge in g.values():
|
---|
1740 | self.assertEqual(len(edge), 3) # each vertex connects to three edges
|
---|
1741 | vertices2 = set(v for edges in g.values() for v in edges)
|
---|
1742 | self.assertEqual(vertices1, vertices2) # edge vertices in original set
|
---|
1743 |
|
---|
1744 | cubefaces = faces(g)
|
---|
1745 | self.assertEqual(len(cubefaces), 6) # six faces
|
---|
1746 | for face in cubefaces:
|
---|
1747 | self.assertEqual(len(face), 4) # each face is a square
|
---|
1748 |
|
---|
1749 | def test_cuboctahedron(self):
|
---|
1750 |
|
---|
1751 | # http://en.wikipedia.org/wiki/Cuboctahedron
|
---|
1752 | # 8 triangular faces and 6 square faces
|
---|
1753 | # 12 indentical vertices each connecting a triangle and square
|
---|
1754 |
|
---|
1755 | g = cube(3)
|
---|
1756 | cuboctahedron = linegraph(g) # V( --> {V1, V2, V3, V4}
|
---|
1757 | self.assertEqual(len(cuboctahedron), 12)# twelve vertices
|
---|
1758 |
|
---|
1759 | vertices = set(cuboctahedron)
|
---|
1760 | for edges in cuboctahedron.values():
|
---|
1761 | self.assertEqual(len(edges), 4) # each vertex connects to four other vertices
|
---|
1762 | othervertices = set(edge for edges in cuboctahedron.values() for edge in edges)
|
---|
1763 | self.assertEqual(vertices, othervertices) # edge vertices in original set
|
---|
1764 |
|
---|
1765 | cubofaces = faces(cuboctahedron)
|
---|
1766 | facesizes = collections.defaultdict(int)
|
---|
1767 | for face in cubofaces:
|
---|
1768 | facesizes[len(face)] += 1
|
---|
1769 | self.assertEqual(facesizes[3], 8) # eight triangular faces
|
---|
1770 | self.assertEqual(facesizes[4], 6) # six square faces
|
---|
1771 |
|
---|
1772 | for vertex in cuboctahedron:
|
---|
1773 | edge = vertex # Cuboctahedron vertices are edges in Cube
|
---|
1774 | self.assertEqual(len(edge), 2) # Two cube vertices define an edge
|
---|
1775 | for cubevert in edge:
|
---|
1776 | self.assertIn(cubevert, g)
|
---|
1777 |
|
---|
1778 |
|
---|
1779 | #==============================================================================
|
---|
1780 |
|
---|
1781 | def test_main(verbose=None):
|
---|
1782 | test_classes = (
|
---|
1783 | TestSet,
|
---|
1784 | TestSetSubclass,
|
---|
1785 | TestSetSubclassWithKeywordArgs,
|
---|
1786 | TestFrozenSet,
|
---|
1787 | TestFrozenSetSubclass,
|
---|
1788 | TestSetOfSets,
|
---|
1789 | TestExceptionPropagation,
|
---|
1790 | TestBasicOpsEmpty,
|
---|
1791 | TestBasicOpsSingleton,
|
---|
1792 | TestBasicOpsTuple,
|
---|
1793 | TestBasicOpsTriple,
|
---|
1794 | TestBinaryOps,
|
---|
1795 | TestUpdateOps,
|
---|
1796 | TestMutate,
|
---|
1797 | TestSubsetEqualEmpty,
|
---|
1798 | TestSubsetEqualNonEmpty,
|
---|
1799 | TestSubsetEmptyNonEmpty,
|
---|
1800 | TestSubsetPartial,
|
---|
1801 | TestSubsetNonOverlap,
|
---|
1802 | TestOnlySetsNumeric,
|
---|
1803 | TestOnlySetsDict,
|
---|
1804 | TestOnlySetsOperator,
|
---|
1805 | TestOnlySetsTuple,
|
---|
1806 | TestOnlySetsString,
|
---|
1807 | TestOnlySetsGenerator,
|
---|
1808 | TestCopyingEmpty,
|
---|
1809 | TestCopyingSingleton,
|
---|
1810 | TestCopyingTriple,
|
---|
1811 | TestCopyingTuple,
|
---|
1812 | TestCopyingNested,
|
---|
1813 | TestIdentities,
|
---|
1814 | TestVariousIteratorArgs,
|
---|
1815 | TestGraphs,
|
---|
1816 | TestWeirdBugs,
|
---|
1817 | )
|
---|
1818 |
|
---|
1819 | test_support.run_unittest(*test_classes)
|
---|
1820 |
|
---|
1821 | # verify reference counting
|
---|
1822 | if verbose and hasattr(sys, "gettotalrefcount"):
|
---|
1823 | import gc
|
---|
1824 | counts = [None] * 5
|
---|
1825 | for i in xrange(len(counts)):
|
---|
1826 | test_support.run_unittest(*test_classes)
|
---|
1827 | gc.collect()
|
---|
1828 | counts[i] = sys.gettotalrefcount()
|
---|
1829 | print counts
|
---|
1830 |
|
---|
1831 | if __name__ == "__main__":
|
---|
1832 | test_main(verbose=True)
|
---|