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