1#!/usr/bin/env python
2
3import unittest, operator, copy, pickle, random
4from test import test_support
5
6test_support.import_module("sets", deprecated=True)
7from sets import Set, ImmutableSet
8
9empty_set = Set()
10
11#==============================================================================
12
13class TestBasicOps(unittest.TestCase):
14
15    def test_repr(self):
16        if self.repr is not None:
17            self.assertEqual(repr(self.set), self.repr)
18
19    def test_length(self):
20        self.assertEqual(len(self.set), self.length)
21
22    def test_self_equality(self):
23        self.assertEqual(self.set, self.set)
24
25    def test_equivalent_equality(self):
26        self.assertEqual(self.set, self.dup)
27
28    def test_copy(self):
29        self.assertEqual(self.set.copy(), self.dup)
30
31    def test_self_union(self):
32        result = self.set | self.set
33        self.assertEqual(result, self.dup)
34
35    def test_empty_union(self):
36        result = self.set | empty_set
37        self.assertEqual(result, self.dup)
38
39    def test_union_empty(self):
40        result = empty_set | self.set
41        self.assertEqual(result, self.dup)
42
43    def test_self_intersection(self):
44        result = self.set & self.set
45        self.assertEqual(result, self.dup)
46
47    def test_empty_intersection(self):
48        result = self.set & empty_set
49        self.assertEqual(result, empty_set)
50
51    def test_intersection_empty(self):
52        result = empty_set & self.set
53        self.assertEqual(result, empty_set)
54
55    def test_self_symmetric_difference(self):
56        result = self.set ^ self.set
57        self.assertEqual(result, empty_set)
58
59    def checkempty_symmetric_difference(self):
60        result = self.set ^ empty_set
61        self.assertEqual(result, self.set)
62
63    def test_self_difference(self):
64        result = self.set - self.set
65        self.assertEqual(result, empty_set)
66
67    def test_empty_difference(self):
68        result = self.set - empty_set
69        self.assertEqual(result, self.dup)
70
71    def test_empty_difference_rev(self):
72        result = empty_set - self.set
73        self.assertEqual(result, empty_set)
74
75    def test_iteration(self):
76        for v in self.set:
77            self.assertIn(v, self.values)
78
79    def test_pickling(self):
80        p = pickle.dumps(self.set)
81        copy = pickle.loads(p)
82        self.assertEqual(self.set, copy,
83                         "%s != %s" % (self.set, copy))
84
85#------------------------------------------------------------------------------
86
87class TestBasicOpsEmpty(TestBasicOps):
88    def setUp(self):
89        self.case   = "empty set"
90        self.values = []
91        self.set    = Set(self.values)
92        self.dup    = Set(self.values)
93        self.length = 0
94        self.repr   = "Set([])"
95
96#------------------------------------------------------------------------------
97
98class TestBasicOpsSingleton(TestBasicOps):
99    def setUp(self):
100        self.case   = "unit set (number)"
101        self.values = [3]
102        self.set    = Set(self.values)
103        self.dup    = Set(self.values)
104        self.length = 1
105        self.repr   = "Set([3])"
106
107    def test_in(self):
108        self.assertTrue(3 in self.set)
109
110    def test_not_in(self):
111        self.assertTrue(2 not in self.set)
112
113#------------------------------------------------------------------------------
114
115class TestBasicOpsTuple(TestBasicOps):
116    def setUp(self):
117        self.case   = "unit set (tuple)"
118        self.values = [(0, "zero")]
119        self.set    = Set(self.values)
120        self.dup    = Set(self.values)
121        self.length = 1
122        self.repr   = "Set([(0, 'zero')])"
123
124    def test_in(self):
125        self.assertTrue((0, "zero") in self.set)
126
127    def test_not_in(self):
128        self.assertTrue(9 not in self.set)
129
130#------------------------------------------------------------------------------
131
132class TestBasicOpsTriple(TestBasicOps):
133    def setUp(self):
134        self.case   = "triple set"
135        self.values = [0, "zero", operator.add]
136        self.set    = Set(self.values)
137        self.dup    = Set(self.values)
138        self.length = 3
139        self.repr   = None
140
141#==============================================================================
142
143def baditer():
144    raise TypeError
145    yield True
146
147def gooditer():
148    yield True
149
150class TestExceptionPropagation(unittest.TestCase):
151    """SF 628246:  Set constructor should not trap iterator TypeErrors"""
152
153    def test_instanceWithException(self):
154        self.assertRaises(TypeError, Set, baditer())
155
156    def test_instancesWithoutException(self):
157        # All of these iterables should load without exception.
158        Set([1,2,3])
159        Set((1,2,3))
160        Set({'one':1, 'two':2, 'three':3})
161        Set(xrange(3))
162        Set('abc')
163        Set(gooditer())
164
165#==============================================================================
166
167class TestSetOfSets(unittest.TestCase):
168    def test_constructor(self):
169        inner = Set([1])
170        outer = Set([inner])
171        element = outer.pop()
172        self.assertEqual(type(element), ImmutableSet)
173        outer.add(inner)        # Rebuild set of sets with .add method
174        outer.remove(inner)
175        self.assertEqual(outer, Set())   # Verify that remove worked
176        outer.discard(inner)    # Absence of KeyError indicates working fine
177
178#==============================================================================
179
180class TestBinaryOps(unittest.TestCase):
181    def setUp(self):
182        self.set = Set((2, 4, 6))
183
184    def test_eq(self):              # SF bug 643115
185        self.assertEqual(self.set, Set({2:1,4:3,6:5}))
186
187    def test_union_subset(self):
188        result = self.set | Set([2])
189        self.assertEqual(result, Set((2, 4, 6)))
190
191    def test_union_superset(self):
192        result = self.set | Set([2, 4, 6, 8])
193        self.assertEqual(result, Set([2, 4, 6, 8]))
194
195    def test_union_overlap(self):
196        result = self.set | Set([3, 4, 5])
197        self.assertEqual(result, Set([2, 3, 4, 5, 6]))
198
199    def test_union_non_overlap(self):
200        result = self.set | Set([8])
201        self.assertEqual(result, Set([2, 4, 6, 8]))
202
203    def test_intersection_subset(self):
204        result = self.set & Set((2, 4))
205        self.assertEqual(result, Set((2, 4)))
206
207    def test_intersection_superset(self):
208        result = self.set & Set([2, 4, 6, 8])
209        self.assertEqual(result, Set([2, 4, 6]))
210
211    def test_intersection_overlap(self):
212        result = self.set & Set([3, 4, 5])
213        self.assertEqual(result, Set([4]))
214
215    def test_intersection_non_overlap(self):
216        result = self.set & Set([8])
217        self.assertEqual(result, empty_set)
218
219    def test_sym_difference_subset(self):
220        result = self.set ^ Set((2, 4))
221        self.assertEqual(result, Set([6]))
222
223    def test_sym_difference_superset(self):
224        result = self.set ^ Set((2, 4, 6, 8))
225        self.assertEqual(result, Set([8]))
226
227    def test_sym_difference_overlap(self):
228        result = self.set ^ Set((3, 4, 5))
229        self.assertEqual(result, Set([2, 3, 5, 6]))
230
231    def test_sym_difference_non_overlap(self):
232        result = self.set ^ Set([8])
233        self.assertEqual(result, Set([2, 4, 6, 8]))
234
235    def test_cmp(self):
236        a, b = Set('a'), Set('b')
237        self.assertRaises(TypeError, cmp, a, b)
238
239        # You can view this as a buglet:  cmp(a, a) does not raise TypeError,
240        # because __eq__ is tried before __cmp__, and a.__eq__(a) returns True,
241        # which Python thinks is good enough to synthesize a cmp() result
242        # without calling __cmp__.
243        self.assertEqual(cmp(a, a), 0)
244
245        self.assertRaises(TypeError, cmp, a, 12)
246        self.assertRaises(TypeError, cmp, "abc", a)
247
248    def test_inplace_on_self(self):
249        t = self.set.copy()
250        t |= t
251        self.assertEqual(t, self.set)
252        t &= t
253        self.assertEqual(t, self.set)
254        t -= t
255        self.assertEqual(len(t), 0)
256        t = self.set.copy()
257        t ^= t
258        self.assertEqual(len(t), 0)
259
260
261#==============================================================================
262
263class TestUpdateOps(unittest.TestCase):
264    def setUp(self):
265        self.set = Set((2, 4, 6))
266
267    def test_union_subset(self):
268        self.set |= Set([2])
269        self.assertEqual(self.set, Set((2, 4, 6)))
270
271    def test_union_superset(self):
272        self.set |= Set([2, 4, 6, 8])
273        self.assertEqual(self.set, Set([2, 4, 6, 8]))
274
275    def test_union_overlap(self):
276        self.set |= Set([3, 4, 5])
277        self.assertEqual(self.set, Set([2, 3, 4, 5, 6]))
278
279    def test_union_non_overlap(self):
280        self.set |= Set([8])
281        self.assertEqual(self.set, Set([2, 4, 6, 8]))
282
283    def test_union_method_call(self):
284        self.set.union_update(Set([3, 4, 5]))
285        self.assertEqual(self.set, Set([2, 3, 4, 5, 6]))
286
287    def test_intersection_subset(self):
288        self.set &= Set((2, 4))
289        self.assertEqual(self.set, Set((2, 4)))
290
291    def test_intersection_superset(self):
292        self.set &= Set([2, 4, 6, 8])
293        self.assertEqual(self.set, Set([2, 4, 6]))
294
295    def test_intersection_overlap(self):
296        self.set &= Set([3, 4, 5])
297        self.assertEqual(self.set, Set([4]))
298
299    def test_intersection_non_overlap(self):
300        self.set &= Set([8])
301        self.assertEqual(self.set, empty_set)
302
303    def test_intersection_method_call(self):
304        self.set.intersection_update(Set([3, 4, 5]))
305        self.assertEqual(self.set, Set([4]))
306
307    def test_sym_difference_subset(self):
308        self.set ^= Set((2, 4))
309        self.assertEqual(self.set, Set([6]))
310
311    def test_sym_difference_superset(self):
312        self.set ^= Set((2, 4, 6, 8))
313        self.assertEqual(self.set, Set([8]))
314
315    def test_sym_difference_overlap(self):
316        self.set ^= Set((3, 4, 5))
317        self.assertEqual(self.set, Set([2, 3, 5, 6]))
318
319    def test_sym_difference_non_overlap(self):
320        self.set ^= Set([8])
321        self.assertEqual(self.set, Set([2, 4, 6, 8]))
322
323    def test_sym_difference_method_call(self):
324        self.set.symmetric_difference_update(Set([3, 4, 5]))
325        self.assertEqual(self.set, Set([2, 3, 5, 6]))
326
327    def test_difference_subset(self):
328        self.set -= Set((2, 4))
329        self.assertEqual(self.set, Set([6]))
330
331    def test_difference_superset(self):
332        self.set -= Set((2, 4, 6, 8))
333        self.assertEqual(self.set, Set([]))
334
335    def test_difference_overlap(self):
336        self.set -= Set((3, 4, 5))
337        self.assertEqual(self.set, Set([2, 6]))
338
339    def test_difference_non_overlap(self):
340        self.set -= Set([8])
341        self.assertEqual(self.set, Set([2, 4, 6]))
342
343    def test_difference_method_call(self):
344        self.set.difference_update(Set([3, 4, 5]))
345        self.assertEqual(self.set, Set([2, 6]))
346
347#==============================================================================
348
349class TestMutate(unittest.TestCase):
350    def setUp(self):
351        self.values = ["a", "b", "c"]
352        self.set = Set(self.values)
353
354    def test_add_present(self):
355        self.set.add("c")
356        self.assertEqual(self.set, Set("abc"))
357
358    def test_add_absent(self):
359        self.set.add("d")
360        self.assertEqual(self.set, Set("abcd"))
361
362    def test_add_until_full(self):
363        tmp = Set()
364        expected_len = 0
365        for v in self.values:
366            tmp.add(v)
367            expected_len += 1
368            self.assertEqual(len(tmp), expected_len)
369        self.assertEqual(tmp, self.set)
370
371    def test_remove_present(self):
372        self.set.remove("b")
373        self.assertEqual(self.set, Set("ac"))
374
375    def test_remove_absent(self):
376        try:
377            self.set.remove("d")
378            self.fail("Removing missing element should have raised LookupError")
379        except LookupError:
380            pass
381
382    def test_remove_until_empty(self):
383        expected_len = len(self.set)
384        for v in self.values:
385            self.set.remove(v)
386            expected_len -= 1
387            self.assertEqual(len(self.set), expected_len)
388
389    def test_discard_present(self):
390        self.set.discard("c")
391        self.assertEqual(self.set, Set("ab"))
392
393    def test_discard_absent(self):
394        self.set.discard("d")
395        self.assertEqual(self.set, Set("abc"))
396
397    def test_clear(self):
398        self.set.clear()
399        self.assertEqual(len(self.set), 0)
400
401    def test_pop(self):
402        popped = {}
403        while self.set:
404            popped[self.set.pop()] = None
405        self.assertEqual(len(popped), len(self.values))
406        for v in self.values:
407            self.assertIn(v, popped)
408
409    def test_update_empty_tuple(self):
410        self.set.union_update(())
411        self.assertEqual(self.set, Set(self.values))
412
413    def test_update_unit_tuple_overlap(self):
414        self.set.union_update(("a",))
415        self.assertEqual(self.set, Set(self.values))
416
417    def test_update_unit_tuple_non_overlap(self):
418        self.set.union_update(("a", "z"))
419        self.assertEqual(self.set, Set(self.values + ["z"]))
420
421#==============================================================================
422
423class TestSubsets(unittest.TestCase):
424
425    case2method = {"<=": "issubset",
426                   ">=": "issuperset",
427                  }
428
429    reverse = {"==": "==",
430               "!=": "!=",
431               "<":  ">",
432               ">":  "<",
433               "<=": ">=",
434               ">=": "<=",
435              }
436
437    def test_issubset(self):
438        x = self.left
439        y = self.right
440        for case in "!=", "==", "<", "<=", ">", ">=":
441            expected = case in self.cases
442            # Test the binary infix spelling.
443            result = eval("x" + case + "y", locals())
444            self.assertEqual(result, expected)
445            # Test the "friendly" method-name spelling, if one exists.
446            if case in TestSubsets.case2method:
447                method = getattr(x, TestSubsets.case2method[case])
448                result = method(y)
449                self.assertEqual(result, expected)
450
451            # Now do the same for the operands reversed.
452            rcase = TestSubsets.reverse[case]
453            result = eval("y" + rcase + "x", locals())
454            self.assertEqual(result, expected)
455            if rcase in TestSubsets.case2method:
456                method = getattr(y, TestSubsets.case2method[rcase])
457                result = method(x)
458                self.assertEqual(result, expected)
459#------------------------------------------------------------------------------
460
461class TestSubsetEqualEmpty(TestSubsets):
462    left  = Set()
463    right = Set()
464    name  = "both empty"
465    cases = "==", "<=", ">="
466
467#------------------------------------------------------------------------------
468
469class TestSubsetEqualNonEmpty(TestSubsets):
470    left  = Set([1, 2])
471    right = Set([1, 2])
472    name  = "equal pair"
473    cases = "==", "<=", ">="
474
475#------------------------------------------------------------------------------
476
477class TestSubsetEmptyNonEmpty(TestSubsets):
478    left  = Set()
479    right = Set([1, 2])
480    name  = "one empty, one non-empty"
481    cases = "!=", "<", "<="
482
483#------------------------------------------------------------------------------
484
485class TestSubsetPartial(TestSubsets):
486    left  = Set([1])
487    right = Set([1, 2])
488    name  = "one a non-empty proper subset of other"
489    cases = "!=", "<", "<="
490
491#------------------------------------------------------------------------------
492
493class TestSubsetNonOverlap(TestSubsets):
494    left  = Set([1])
495    right = Set([2])
496    name  = "neither empty, neither contains"
497    cases = "!="
498
499#==============================================================================
500
501class TestOnlySetsInBinaryOps(unittest.TestCase):
502
503    def test_eq_ne(self):
504        # Unlike the others, this is testing that == and != *are* allowed.
505        self.assertEqual(self.other == self.set, False)
506        self.assertEqual(self.set == self.other, False)
507        self.assertEqual(self.other != self.set, True)
508        self.assertEqual(self.set != self.other, True)
509
510    def test_ge_gt_le_lt(self):
511        self.assertRaises(TypeError, lambda: self.set < self.other)
512        self.assertRaises(TypeError, lambda: self.set <= self.other)
513        self.assertRaises(TypeError, lambda: self.set > self.other)
514        self.assertRaises(TypeError, lambda: self.set >= self.other)
515
516        self.assertRaises(TypeError, lambda: self.other < self.set)
517        self.assertRaises(TypeError, lambda: self.other <= self.set)
518        self.assertRaises(TypeError, lambda: self.other > self.set)
519        self.assertRaises(TypeError, lambda: self.other >= self.set)
520
521    def test_union_update_operator(self):
522        try:
523            self.set |= self.other
524        except TypeError:
525            pass
526        else:
527            self.fail("expected TypeError")
528
529    def test_union_update(self):
530        if self.otherIsIterable:
531            self.set.union_update(self.other)
532        else:
533            self.assertRaises(TypeError, self.set.union_update, self.other)
534
535    def test_union(self):
536        self.assertRaises(TypeError, lambda: self.set | self.other)
537        self.assertRaises(TypeError, lambda: self.other | self.set)
538        if self.otherIsIterable:
539            self.set.union(self.other)
540        else:
541            self.assertRaises(TypeError, self.set.union, self.other)
542
543    def test_intersection_update_operator(self):
544        try:
545            self.set &= self.other
546        except TypeError:
547            pass
548        else:
549            self.fail("expected TypeError")
550
551    def test_intersection_update(self):
552        if self.otherIsIterable:
553            self.set.intersection_update(self.other)
554        else:
555            self.assertRaises(TypeError,
556                              self.set.intersection_update,
557                              self.other)
558
559    def test_intersection(self):
560        self.assertRaises(TypeError, lambda: self.set & self.other)
561        self.assertRaises(TypeError, lambda: self.other & self.set)
562        if self.otherIsIterable:
563            self.set.intersection(self.other)
564        else:
565            self.assertRaises(TypeError, self.set.intersection, self.other)
566
567    def test_sym_difference_update_operator(self):
568        try:
569            self.set ^= self.other
570        except TypeError:
571            pass
572        else:
573            self.fail("expected TypeError")
574
575    def test_sym_difference_update(self):
576        if self.otherIsIterable:
577            self.set.symmetric_difference_update(self.other)
578        else:
579            self.assertRaises(TypeError,
580                              self.set.symmetric_difference_update,
581                              self.other)
582
583    def test_sym_difference(self):
584        self.assertRaises(TypeError, lambda: self.set ^ self.other)
585        self.assertRaises(TypeError, lambda: self.other ^ self.set)
586        if self.otherIsIterable:
587            self.set.symmetric_difference(self.other)
588        else:
589            self.assertRaises(TypeError, self.set.symmetric_difference, self.other)
590
591    def test_difference_update_operator(self):
592        try:
593            self.set -= self.other
594        except TypeError:
595            pass
596        else:
597            self.fail("expected TypeError")
598
599    def test_difference_update(self):
600        if self.otherIsIterable:
601            self.set.difference_update(self.other)
602        else:
603            self.assertRaises(TypeError,
604                              self.set.difference_update,
605                              self.other)
606
607    def test_difference(self):
608        self.assertRaises(TypeError, lambda: self.set - self.other)
609        self.assertRaises(TypeError, lambda: self.other - self.set)
610        if self.otherIsIterable:
611            self.set.difference(self.other)
612        else:
613            self.assertRaises(TypeError, self.set.difference, self.other)
614
615#------------------------------------------------------------------------------
616
617class TestOnlySetsNumeric(TestOnlySetsInBinaryOps):
618    def setUp(self):
619        self.set   = Set((1, 2, 3))
620        self.other = 19
621        self.otherIsIterable = False
622
623#------------------------------------------------------------------------------
624
625class TestOnlySetsDict(TestOnlySetsInBinaryOps):
626    def setUp(self):
627        self.set   = Set((1, 2, 3))
628        self.other = {1:2, 3:4}
629        self.otherIsIterable = True
630
631#------------------------------------------------------------------------------
632
633class TestOnlySetsOperator(TestOnlySetsInBinaryOps):
634    def setUp(self):
635        self.set   = Set((1, 2, 3))
636        self.other = operator.add
637        self.otherIsIterable = False
638
639    def test_ge_gt_le_lt(self):
640        with test_support.check_py3k_warnings():
641            super(TestOnlySetsOperator, self).test_ge_gt_le_lt()
642
643#------------------------------------------------------------------------------
644
645class TestOnlySetsTuple(TestOnlySetsInBinaryOps):
646    def setUp(self):
647        self.set   = Set((1, 2, 3))
648        self.other = (2, 4, 6)
649        self.otherIsIterable = True
650
651#------------------------------------------------------------------------------
652
653class TestOnlySetsString(TestOnlySetsInBinaryOps):
654    def setUp(self):
655        self.set   = Set((1, 2, 3))
656        self.other = 'abc'
657        self.otherIsIterable = True
658
659#------------------------------------------------------------------------------
660
661class TestOnlySetsGenerator(TestOnlySetsInBinaryOps):
662    def setUp(self):
663        def gen():
664            for i in xrange(0, 10, 2):
665                yield i
666        self.set   = Set((1, 2, 3))
667        self.other = gen()
668        self.otherIsIterable = True
669
670#------------------------------------------------------------------------------
671
672class TestOnlySetsofSets(TestOnlySetsInBinaryOps):
673    def setUp(self):
674        self.set   = Set((1, 2, 3))
675        self.other = [Set('ab'), ImmutableSet('cd')]
676        self.otherIsIterable = True
677
678#==============================================================================
679
680class TestCopying(unittest.TestCase):
681
682    def test_copy(self):
683        dup = self.set.copy()
684        self.assertEqual(len(dup), len(self.set))
685        dup_list = sorted(dup)
686        set_list = sorted(self.set)
687        self.assertEqual(len(dup_list), len(set_list))
688        for i, el in enumerate(dup_list):
689            self.assertIs(el, set_list[i])
690
691    def test_deep_copy(self):
692        dup = copy.deepcopy(self.set)
693        self.assertSetEqual(dup, self.set)
694
695#------------------------------------------------------------------------------
696
697class TestCopyingEmpty(TestCopying):
698    def setUp(self):
699        self.set = Set()
700
701#------------------------------------------------------------------------------
702
703class TestCopyingSingleton(TestCopying):
704    def setUp(self):
705        self.set = Set(["hello"])
706
707#------------------------------------------------------------------------------
708
709class TestCopyingTriple(TestCopying):
710    def setUp(self):
711        self.set = Set(["zero", 0, None])
712
713    def test_copy(self):
714        with test_support.check_py3k_warnings():
715            super(TestCopyingTriple, self).test_copy()
716
717#------------------------------------------------------------------------------
718
719class TestCopyingTuple(TestCopying):
720    def setUp(self):
721        self.set = Set([(1, 2)])
722
723#------------------------------------------------------------------------------
724
725class TestCopyingNested(TestCopying):
726    def setUp(self):
727        self.set = Set([((1, 2), (3, 4))])
728
729#==============================================================================
730
731class TestIdentities(unittest.TestCase):
732    def setUp(self):
733        self.a = Set([random.randrange(100) for i in xrange(50)])
734        self.b = Set([random.randrange(100) for i in xrange(50)])
735
736    def test_binopsVsSubsets(self):
737        a, b = self.a, self.b
738        self.assertTrue(a - b <= a)
739        self.assertTrue(b - a <= b)
740        self.assertTrue(a & b <= a)
741        self.assertTrue(a & b <= b)
742        self.assertTrue(a | b >= a)
743        self.assertTrue(a | b >= b)
744        self.assertTrue(a ^ b <= a | b)
745
746    def test_commutativity(self):
747        a, b = self.a, self.b
748        self.assertEqual(a&b, b&a)
749        self.assertEqual(a|b, b|a)
750        self.assertEqual(a^b, b^a)
751        if a != b:
752            self.assertNotEqual(a-b, b-a)
753
754    def test_reflexsive_relations(self):
755        a, zero = self.a, Set()
756        self.assertEqual(a ^ a, zero)
757        self.assertEqual(a - a, zero)
758        self.assertEqual(a | a, a)
759        self.assertEqual(a & a, a)
760        self.assertTrue(a <= a)
761        self.assertTrue(a >= a)
762        self.assertTrue(a == a)
763
764    def test_summations(self):
765        # check that sums of parts equal the whole
766        a, b = self.a, self.b
767        self.assertEqual((a-b)|(a&b)|(b-a), a|b)
768        self.assertEqual((a&b)|(a^b), a|b)
769        self.assertEqual(a|(b-a), a|b)
770        self.assertEqual((a-b)|b, a|b)
771        self.assertEqual((a-b)|(a&b), a)
772        self.assertEqual((b-a)|(a&b), b)
773        self.assertEqual((a-b)|(b-a), a^b)
774
775    def test_exclusion(self):
776        # check that inverse operations do not overlap
777        a, b, zero = self.a, self.b, Set()
778        self.assertEqual((a-b)&b, zero)
779        self.assertEqual((b-a)&a, zero)
780        self.assertEqual((a&b)&(a^b), zero)
781
782    def test_cardinality_relations(self):
783        a, b = self.a, self.b
784        self.assertEqual(len(a), len(a-b) + len(a&b))
785        self.assertEqual(len(b), len(b-a) + len(a&b))
786        self.assertEqual(len(a^b), len(a-b) + len(b-a))
787        self.assertEqual(len(a|b), len(a-b) + len(a&b) + len(b-a))
788        self.assertEqual(len(a^b) + len(a&b), len(a|b))
789
790#==============================================================================
791
792libreftest = """
793Example from the Library Reference:  Doc/lib/libsets.tex
794
795>>> from sets import Set as Base  # override _repr to get sorted output
796>>> class Set(Base):
797...     def _repr(self):
798...         return Base._repr(self, sorted=True)
799>>> engineers = Set(['John', 'Jane', 'Jack', 'Janice'])
800>>> programmers = Set(['Jack', 'Sam', 'Susan', 'Janice'])
801>>> managers = Set(['Jane', 'Jack', 'Susan', 'Zack'])
802>>> employees = engineers | programmers | managers           # union
803>>> engineering_management = engineers & managers            # intersection
804>>> fulltime_management = managers - engineers - programmers # difference
805>>> engineers.add('Marvin')
806>>> print engineers
807Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin'])
808>>> employees.issuperset(engineers)           # superset test
809False
810>>> employees.union_update(engineers)         # update from another set
811>>> employees.issuperset(engineers)
812True
813>>> for group in [engineers, programmers, managers, employees]:
814...     group.discard('Susan')                # unconditionally remove element
815...     print group
816...
817Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin'])
818Set(['Jack', 'Janice', 'Sam'])
819Set(['Jack', 'Jane', 'Zack'])
820Set(['Jack', 'Jane', 'Janice', 'John', 'Marvin', 'Sam', 'Zack'])
821"""
822
823#==============================================================================
824
825__test__ = {'libreftest' : libreftest}
826
827def test_main(verbose=None):
828    import doctest
829    from test import test_sets
830    test_support.run_unittest(
831        TestSetOfSets,
832        TestExceptionPropagation,
833        TestBasicOpsEmpty,
834        TestBasicOpsSingleton,
835        TestBasicOpsTuple,
836        TestBasicOpsTriple,
837        TestBinaryOps,
838        TestUpdateOps,
839        TestMutate,
840        TestSubsetEqualEmpty,
841        TestSubsetEqualNonEmpty,
842        TestSubsetEmptyNonEmpty,
843        TestSubsetPartial,
844        TestSubsetNonOverlap,
845        TestOnlySetsNumeric,
846        TestOnlySetsDict,
847        TestOnlySetsOperator,
848        TestOnlySetsTuple,
849        TestOnlySetsString,
850        TestOnlySetsGenerator,
851        TestOnlySetsofSets,
852        TestCopyingEmpty,
853        TestCopyingSingleton,
854        TestCopyingTriple,
855        TestCopyingTuple,
856        TestCopyingNested,
857        TestIdentities,
858        doctest.DocTestSuite(test_sets),
859    )
860
861if __name__ == "__main__":
862    test_main(verbose=True)
863