1e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport unittest 2e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordfrom test import test_support 3e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordfrom weakref import proxy, ref, WeakSet 4e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport operator 5e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport copy 6e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport string 7e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport os 8e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordfrom random import randrange, shuffle 9e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport sys 10e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport warnings 11e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport collections 12e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport gc 13e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordimport contextlib 14e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 15e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 16e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordclass Foo: 17e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord pass 18e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 19e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordclass SomeClass(object): 20e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def __init__(self, value): 21e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.value = value 22e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def __eq__(self, other): 23e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if type(other) != type(self): 24e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord return False 25e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord return other.value == self.value 26e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 27e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def __ne__(self, other): 28e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord return not self.__eq__(other) 29e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 30e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def __hash__(self): 31e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord return hash((SomeClass, self.value)) 32e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 33c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrouclass RefCycle(object): 34c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou def __init__(self): 35c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.cycle = self 36c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou 37e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordclass TestWeakSet(unittest.TestCase): 38e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 39e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def setUp(self): 40e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # need to keep references to them 41e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.items = [SomeClass(c) for c in ('a', 'b', 'c')] 42e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.items2 = [SomeClass(c) for c in ('x', 'y', 'z')] 43e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.letters = [SomeClass(c) for c in string.ascii_letters] 44104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.ab_items = [SomeClass(c) for c in 'ab'] 45104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.abcde_items = [SomeClass(c) for c in 'abcde'] 46104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.def_items = [SomeClass(c) for c in 'def'] 47104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.ab_weakset = WeakSet(self.ab_items) 48104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.abcde_weakset = WeakSet(self.abcde_items) 49104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.def_weakset = WeakSet(self.def_items) 50e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s = WeakSet(self.items) 51e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.d = dict.fromkeys(self.items) 52e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.obj = SomeClass('F') 53e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.fs = WeakSet([self.obj]) 54e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 55e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_methods(self): 56e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord weaksetmethods = dir(WeakSet) 57e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for method in dir(set): 58e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if method == 'test_c_api' or method.startswith('_'): 59e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord continue 60e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(method, weaksetmethods, 61e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord "WeakSet missing method " + method) 62e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 63e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_new_or_init(self): 64e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, WeakSet, [], 2) 65e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 66e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_len(self): 67e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(self.s), len(self.d)) 68e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(self.fs), 1) 69e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord del self.obj 70e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(self.fs), 0) 71e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 72e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_contains(self): 73e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in self.letters: 74e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(c in self.s, c in self.d) 7552f839540c27027bff4c65efe704e8691a16b4e0Georg Brandl # 1 is not weakref'able, but that TypeError is caught by __contains__ 7652f839540c27027bff4c65efe704e8691a16b4e0Georg Brandl self.assertNotIn(1, self.s) 77e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(self.obj, self.fs) 78e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord del self.obj 79e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(SomeClass('F'), self.fs) 80e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 81e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_union(self): 82e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord u = self.s.union(self.items2) 83e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in self.letters: 84e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(c in u, c in self.d or c in self.items2) 85e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, WeakSet(self.items)) 86e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(type(u), WeakSet) 87e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.union, [[]]) 88e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for C in set, frozenset, dict.fromkeys, list, tuple: 89e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord x = WeakSet(self.items + self.items2) 90e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord c = C(self.items2) 91e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s.union(c), x) 9294c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou del c 9394c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(u), len(self.items) + len(self.items2)) 9494c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.items2.pop() 9594c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou gc.collect() 9694c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(u), len(self.items) + len(self.items2)) 97e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 98e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_or(self): 99e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.union(self.items2) 100e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s | set(self.items2), i) 101e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s | frozenset(self.items2), i) 102e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 103e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_intersection(self): 10494c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou s = WeakSet(self.letters) 10594c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou i = s.intersection(self.items2) 106e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in self.letters: 10794c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(c in i, c in self.items2 and c in self.letters) 10894c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(s, WeakSet(self.letters)) 109e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(type(i), WeakSet) 110e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for C in set, frozenset, dict.fromkeys, list, tuple: 111e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord x = WeakSet([]) 11294c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(i.intersection(C(self.items)), x) 11394c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(i), len(self.items2)) 11494c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.items2.pop() 11594c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou gc.collect() 11694c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(i), len(self.items2)) 117e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 118e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_isdisjoint(self): 119e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(self.s.isdisjoint(WeakSet(self.items2))) 120e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(not self.s.isdisjoint(WeakSet(self.letters))) 121e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 122e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_and(self): 123e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.intersection(self.items2) 124e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s & set(self.items2), i) 125e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s & frozenset(self.items2), i) 126e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 127e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_difference(self): 128e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.difference(self.items2) 129e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in self.letters: 130e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(c in i, c in self.d and c not in self.items2) 131e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, WeakSet(self.items)) 132e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(type(i), WeakSet) 133e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.difference, [[]]) 134e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 135e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_sub(self): 136e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.difference(self.items2) 137e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s - set(self.items2), i) 138e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s - frozenset(self.items2), i) 139e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 140e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_symmetric_difference(self): 141e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.symmetric_difference(self.items2) 142e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in self.letters: 143e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(c in i, (c in self.d) ^ (c in self.items2)) 144e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, WeakSet(self.items)) 145e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(type(i), WeakSet) 146e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.symmetric_difference, [[]]) 14794c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(i), len(self.items) + len(self.items2)) 14894c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.items2.pop() 14994c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou gc.collect() 15094c2d6df544abd9eb0601cb5387774599cf0cdf1Antoine Pitrou self.assertEqual(len(i), len(self.items) + len(self.items2)) 151e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 152e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_xor(self): 153e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord i = self.s.symmetric_difference(self.items2) 154e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s ^ set(self.items2), i) 155e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s ^ frozenset(self.items2), i) 156e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 157e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_sub_and_super(self): 158104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertTrue(self.ab_weakset <= self.abcde_weakset) 159104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertTrue(self.abcde_weakset <= self.abcde_weakset) 160104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertTrue(self.abcde_weakset >= self.ab_weakset) 161104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.abcde_weakset <= self.def_weakset) 162104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.abcde_weakset >= self.def_weakset) 163e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(set('a').issubset('abc')) 164e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(set('abc').issuperset('a')) 165e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(set('a').issubset('cbs')) 166e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(set('cbs').issuperset('a')) 167e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 168104f18977fc23b7df415fda1bbb7125feece553fMeador Inge def test_lt(self): 169104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertTrue(self.ab_weakset < self.abcde_weakset) 170104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.abcde_weakset < self.def_weakset) 171104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.ab_weakset < self.ab_weakset) 172104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(WeakSet() < WeakSet()) 173104f18977fc23b7df415fda1bbb7125feece553fMeador Inge 174104f18977fc23b7df415fda1bbb7125feece553fMeador Inge def test_gt(self): 175104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertTrue(self.abcde_weakset > self.ab_weakset) 176104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.abcde_weakset > self.def_weakset) 177104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(self.ab_weakset > self.ab_weakset) 178104f18977fc23b7df415fda1bbb7125feece553fMeador Inge self.assertFalse(WeakSet() > WeakSet()) 179104f18977fc23b7df415fda1bbb7125feece553fMeador Inge 180e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_gc(self): 181e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Create a nest of cycles to exercise overall ref count check 182e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s = WeakSet(Foo() for i in range(1000)) 183e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for elem in s: 184e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord elem.cycle = s 185e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord elem.sub = elem 186e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord elem.set = WeakSet([elem]) 187e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 188e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_subclass_with_custom_hash(self): 189e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Bug #1257731 190e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord class H(WeakSet): 191e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def __hash__(self): 192e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord return int(id(self) & 0x7fffffff) 193e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s=H() 194e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord f=set() 195e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord f.add(s) 196e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(s, f) 197e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord f.remove(s) 198e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord f.add(s) 199e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord f.discard(s) 200e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 201e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_init(self): 202e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s = WeakSet() 203e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s.__init__(self.items) 204e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(s, self.s) 205e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s.__init__(self.items2) 206e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(s, WeakSet(self.items2)) 207e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, s.__init__, s, 2); 208e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, s.__init__, 1); 209e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 210e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_constructor_identity(self): 211e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s = WeakSet(self.items) 212e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t = WeakSet(s) 213e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotEqual(id(s), id(t)) 214e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 215e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_hash(self): 216e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, hash, self.s) 217e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 218e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_clear(self): 219e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.clear() 220e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, WeakSet([])) 221e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(self.s), 0) 222e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 223e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_copy(self): 224e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord dup = self.s.copy() 225e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, dup) 226e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotEqual(id(self.s), id(dup)) 227e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 228e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_add(self): 229e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord x = SomeClass('Q') 230e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.add(x) 231e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(x, self.s) 232e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord dup = self.s.copy() 233e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.add(x) 234e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(self.s, dup) 235e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.add, []) 236e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.fs.add(Foo()) 237e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(len(self.fs) == 1) 238e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.fs.add(self.obj) 239e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(len(self.fs) == 1) 240e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 241e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_remove(self): 242e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord x = SomeClass('a') 243e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.remove(x) 244e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(x, self.s) 245e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(KeyError, self.s.remove, x) 246e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.remove, []) 247e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 248e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_discard(self): 249e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord a, q = SomeClass('a'), SomeClass('Q') 250e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.discard(a) 251e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(a, self.s) 252e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.discard(q) 253e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.discard, []) 254e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 255e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_pop(self): 256e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for i in range(len(self.s)): 257e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord elem = self.s.pop() 258e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(elem, self.s) 259e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(KeyError, self.s.pop) 260e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 261e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_update(self): 262e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord retval = self.s.update(self.items2) 263e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(retval, None) 264e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 265e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 266e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.update, [[]]) 267e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 268e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_update_set(self): 269e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s.update(set(self.items2)) 270e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 271e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 272e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 273e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_ior(self): 274e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s |= set(self.items2) 275e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 276e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 277e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 278e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_intersection_update(self): 279e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord retval = self.s.intersection_update(self.items2) 280e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(retval, None) 281e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 282e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if c in self.items2 and c in self.items: 283e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 284e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 285e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 286e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.intersection_update, [[]]) 287e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 288e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_iand(self): 289e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s &= set(self.items2) 290e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 291e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if c in self.items2 and c in self.items: 292e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 293e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 294e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 295e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 296e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_difference_update(self): 297e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord retval = self.s.difference_update(self.items2) 298e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(retval, None) 299e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 300e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if c in self.items and c not in self.items2: 301e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 302e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 303e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 304e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.difference_update, [[]]) 305e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]]) 306e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 307e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_isub(self): 308e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s -= set(self.items2) 309e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 310e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if c in self.items and c not in self.items2: 311e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 312e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 313e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 314e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 315e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_symmetric_difference_update(self): 316e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord retval = self.s.symmetric_difference_update(self.items2) 317e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(retval, None) 318e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 319e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if (c in self.items) ^ (c in self.items2): 320e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 321e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 322e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 323e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]]) 324e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 325e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_ixor(self): 326e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.s ^= set(self.items2) 327e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord for c in (self.items + self.items2): 328e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord if (c in self.items) ^ (c in self.items2): 329e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(c, self.s) 330e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord else: 331e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(c, self.s) 332e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 333e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_inplace_on_self(self): 334e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t = self.s.copy() 335e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t |= t 336e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(t, self.s) 337e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t &= t 338e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(t, self.s) 339e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t -= t 340e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(t, WeakSet()) 341e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t = self.s.copy() 342e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t ^= t 343e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(t, WeakSet()) 344e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 345e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_eq(self): 346e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # issue 5964 347e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(self.s == self.s) 348e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertTrue(self.s == WeakSet(self.items)) 349e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(self.s == set(self.items)) 350e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(self.s == list(self.items)) 351e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(self.s == tuple(self.items)) 352e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertFalse(self.s == 1) 353e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 3541cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson def test_ne(self): 3551cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson self.assertTrue(self.s != set(self.items)) 3561cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson s1 = WeakSet() 3571cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson s2 = WeakSet() 3581cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson self.assertFalse(s1 != s2) 3591cf48b4adc0589dd52d123ddb6e5976c40ed2da5Benjamin Peterson 360e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_weak_destroy_while_iterating(self): 361e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Issue #7105: iterators shouldn't crash when a key is implicitly removed 362e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Create new items to be sure no-one else holds a reference 363e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord items = [SomeClass(c) for c in ('a', 'b', 'c')] 364e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s = WeakSet(items) 365e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord it = iter(s) 366e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord next(it) # Trigger internal iteration 367e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Destroy an item 368e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord del items[-1] 369e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord gc.collect() # just in case 370e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # We have removed either the first consumed items, or another one 371e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(len(list(it)), [len(items), len(items) - 1]) 372e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord del it 373e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # The removal has been committed 374e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(s), len(items)) 375e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 376e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def test_weak_destroy_and_mutate_while_iterating(self): 377e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Issue #7105: iterators shouldn't crash when a key is implicitly removed 378e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord items = [SomeClass(c) for c in string.ascii_letters] 379e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s = WeakSet(items) 380e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord @contextlib.contextmanager 381e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord def testcontext(): 382e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord try: 383e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord it = iter(s) 384e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord next(it) 385e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord # Schedule an item for removal and recreate it 386e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord u = SomeClass(str(items.pop())) 387e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord gc.collect() # just in case 388e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord yield u 389e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord finally: 390e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord it = None # should commit all removals 391e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 392e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord with testcontext() as u: 393e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(u, s) 394e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord with testcontext() as u: 395e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertRaises(KeyError, s.remove, u) 396e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertNotIn(u, s) 397e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord with testcontext() as u: 398e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s.add(u) 399e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertIn(u, s) 400e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord t = s.copy() 401e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord with testcontext() as u: 402e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s.update(t) 403e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(s), len(t)) 404e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord with testcontext() as u: 405e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord s.clear() 406e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord self.assertEqual(len(s), 0) 407e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 408c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou def test_len_cycles(self): 409c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou N = 20 410c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou items = [RefCycle() for i in range(N)] 411c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou s = WeakSet(items) 412c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou del items 413c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou it = iter(s) 414c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou try: 415c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou next(it) 416c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou except StopIteration: 417c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou pass 418c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou gc.collect() 419c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou n1 = len(s) 420c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou del it 421c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou gc.collect() 422c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou n2 = len(s) 423c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou # one item may be kept alive inside the iterator 424c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertIn(n1, (0, 1)) 425c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertEqual(n2, 0) 426c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou 427c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou def test_len_race(self): 428c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou # Extended sanity checks for len() in the face of cyclic collection 429c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.addCleanup(gc.set_threshold, *gc.get_threshold()) 430c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou for th in range(1, 100): 431c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou N = 20 432c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou gc.collect(0) 433c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou gc.set_threshold(th, th, th) 434c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou items = [RefCycle() for i in range(N)] 435c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou s = WeakSet(items) 436c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou del items 437c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou # All items will be collected at next garbage collection pass 438c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou it = iter(s) 439c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou try: 440c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou next(it) 441c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou except StopIteration: 442c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou pass 443c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou n1 = len(s) 444c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou del it 445c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou n2 = len(s) 446c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertGreaterEqual(n1, 0) 447c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertLessEqual(n1, N) 448c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertGreaterEqual(n2, 0) 449c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou self.assertLessEqual(n2, n1) 450c56bca31e9b7ac87a459a65680ee7ad454fd4f22Antoine Pitrou 451e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 452e6410c536c9dca5a3a7899888c071f41a1767291Michael Foorddef test_main(verbose=None): 453e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord test_support.run_unittest(TestWeakSet) 454e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord 455e6410c536c9dca5a3a7899888c071f41a1767291Michael Foordif __name__ == "__main__": 456e6410c536c9dca5a3a7899888c071f41a1767291Michael Foord test_main(verbose=True) 457