1from PyObjCTools.TestSupport import * 2import objc 3from PyObjCTest.test_object_property import OCObserve 4import sys 5import pickle 6 7NSObject = objc.lookUpClass('NSObject') 8 9class TestSetPropertyHelper (NSObject): 10 aSet = objc.set_property() 11 aSet2 = objc.set_property() 12 aROSet = objc.set_property(read_only=True) 13 14class TestSetProperty (TestCase): 15 def testCopying(self): 16 o = TestSetPropertyHelper.alloc().init() 17 aSet = set([1,2]) 18 o.aSet = aSet 19 20 self.assertEqual(len(o.aSet), 2) 21 self.assertEqual(len(aSet), 2) 22 aSet.add(3) 23 self.assertEqual(len(o.aSet), 2) 24 self.assertEqual(len(aSet), 3) 25 26 def testRepr(self): 27 o = TestSetPropertyHelper.alloc().init() 28 aSet = set([1,2]) 29 o.aSet = aSet 30 31 self.assertEqual(repr(o.aSet), '<set proxy for property aSet %r>'%(aSet,)) 32 33 def testDefault(self): 34 with OCObserve.alloc().init() as observer: 35 o = TestSetPropertyHelper.alloc().init() 36 37 observer.register(o, 'aSet') 38 39 o.aSet = set() 40 self.assertEqual(observer.seen, {'aSet': set()}) 41 42 43 self.assertEqual(len(o.aSet), 0) 44 o.aSet.add('a') 45 o.aSet.add('b') 46 self.assertEqual(len(o.aSet), 2) 47 self.assertEqual(observer.seen, {'aSet': {'b'}}) 48 49 self.assertEqual(observer.values[-2][-1]['kind'], 2) 50 self.assertNotIn('old', observer.values[-2][-1]) 51 self.assertEqual(observer.values[-2][-1]['new'], set('a')) 52 53 self.assertEqual(observer.values[-1][-1]['kind'], 2) 54 self.assertNotIn('old', observer.values[-1][-1]) 55 self.assertEqual(observer.values[-1][-1]['new'], set('b')) 56 57 v = list(o.aSet) 58 v.sort() 59 self.assertEqual(v, ['a', 'b']) 60 61 self.assertEqual(o.aSet, set(['a', 'b'])) 62 63 proxy = o.aSet 64 65 66 o.aSet.clear() 67 self.assertEqual(len(o.aSet), 0) 68 self.assertEqual(len(proxy), 0) 69 70 self.assertEqual(observer.values[-1][-1]['old'], set(['a', 'b'])) 71 self.assertNotIn('new', observer.values[-1][-1]) 72 73 def testForwarding(self): 74 o = TestSetPropertyHelper.alloc().init() 75 o.aSet = set() 76 77 self.assertTrue(o.aSet.issubset({1,2})) 78 79 def testSetting(self): 80 o = TestSetPropertyHelper.alloc().init() 81 s = {1,2} 82 o.aSet = s 83 self.assertEqual(o.aSet, s) 84 s.add(3) 85 self.assertNotEqual(o.aSet, s) 86 o.aSet2 = o.aSet 87 o.aSet.add(4) 88 self.assertNotEqual(o.aSet, o.aSet2) 89 90 v = o.aSet 91 o._aSet = None 92 self.assertEqual(v, set()) 93 94 95 96 97 def testDifferenceUpdate(self): 98 with OCObserve.alloc().init() as observer: 99 o = TestSetPropertyHelper.alloc().init() 100 101 o.aSet.add(1) 102 o.aSet.add(2) 103 o.aSet.add(3) 104 105 observer.register(o, 'aSet') 106 107 o.aSet.difference_update(set([1,4])) 108 self.assertEqual(o.aSet, set([2,3])) 109 110 self.assertEqual(len(observer.values), 1) 111 self.assertEqual(observer.values[-1][-1]['kind'], 3) 112 self.assertNotIn('new', observer.values[-1][-1]) 113 self.assertEqual(observer.values[-1][-1]['old'], set([1])) 114 115 def testSymmetricDifferenceUpdate(self): 116 with OCObserve.alloc().init() as observer: 117 o = TestSetPropertyHelper.alloc().init() 118 119 o.aSet = set([1,2,3]) 120 121 observer.register(o, 'aSet') 122 123 self.assertEqual(len(observer.values), 0) 124 o.aSet.symmetric_difference_update(set([1,4])) 125 self.assertEqual(o.aSet, set([2, 3, 4])) 126 127 self.assertEqual(len(observer.values), 2) 128 129 haveAdd = False 130 haveRemove = False 131 132 for i in 0, 1: 133 if observer.values[i][-1]['kind'] == 3: 134 # Remove 135 self.assertNotIn('new', observer.values[i][-1]) 136 self.assertEqual(observer.values[i][-1]['old'], set([1])) 137 haveRemove = True 138 139 elif observer.values[i][-1]['kind'] == 2: 140 # Remove 141 self.assertNotIn('old', observer.values[i][-1]) 142 self.assertEqual(observer.values[i][-1]['new'], set([4])) 143 haveAdd = True 144 145 else: 146 self.fail("Unexpected update kind") 147 148 if not haveAdd and haveRemove: 149 self.fail("Do not have both an add and remove notification") 150 151 def testUpdate(self): 152 with OCObserve.alloc().init() as observer: 153 o = TestSetPropertyHelper.alloc().init() 154 observer.register(o, 'aSet') 155 self.assertEqual(o.aSet, set()) 156 self.assertEqual(len(observer.values), 1) 157 158 o.aSet.update([1,2,3]) 159 self.assertEqual(len(observer.values), 2) 160 self.assertEqual(observer.values[-1][-1]['kind'], 2) 161 self.assertNotIn('old', observer.values[-1][-1]) 162 self.assertEqual(observer.values[-1][-1]['new'], set([1, 2, 3])) 163 164 o.aSet.update(set([3,4,5])) 165 self.assertEqual(len(observer.values), 3) 166 self.assertEqual(observer.values[-1][-1]['kind'], 2) 167 self.assertNotIn('old', observer.values[-1][-1]) 168 self.assertEqual(observer.values[-1][-1]['new'], set([4, 5])) 169 170 171 172 def testAddDiscard(self): 173 with OCObserve.alloc().init() as observer: 174 o = TestSetPropertyHelper.alloc().init() 175 observer.register(o, 'aSet') 176 177 o.aSet.add(1) 178 self.assertEqual(observer.seen, {'aSet': {1}}) 179 self.assertNotIn('old', observer.values[-1][-1]) 180 self.assertEqual(observer.values[-1][-1]['new'], set([1])) 181 182 o.aSet.discard(1) 183 self.assertNotIn('new', observer.values[-1][-1]) 184 self.assertEqual(observer.values[-1][-1]['old'], set([1])) 185 186 o.aSet.discard(2) 187 self.assertNotIn('new', observer.values[-1][-1]) 188 self.assertEqual(observer.values[-1][-1]['old'], set([])) 189 190 191 def testAddRemove(self): 192 with OCObserve.alloc().init() as observer: 193 o = TestSetPropertyHelper.alloc().init() 194 observer.register(o, 'aSet') 195 196 o.aSet.add(1) 197 self.assertEqual(observer.seen, {'aSet': {1}}) 198 self.assertNotIn('old', observer.values[-1][-1]) 199 self.assertEqual(observer.values[-1][-1]['new'], set([1])) 200 201 o.aSet.remove(1) 202 self.assertNotIn('new', observer.values[-1][-1]) 203 self.assertEqual(observer.values[-1][-1]['old'], set([1])) 204 205 self.assertRaises(KeyError, o.aSet.remove, 2) 206 self.assertNotIn('new', observer.values[-1][-1]) 207 self.assertEqual(observer.values[-1][-1]['old'], set([])) 208 209 o.aSet.add(1) 210 o.aSet.add(2) 211 v = o.aSet.pop() 212 self.assertTrue(v in (1, 2)) 213 self.assertNotIn('new', observer.values[-1][-1]) 214 self.assertEqual(observer.values[-1][-1]['old'], set([v])) 215 216 o.aSet = set() 217 self.assertRaises(KeyError, o.aSet.pop) 218 219 def testOperators(self): 220 with OCObserve.alloc().init() as observer: 221 o = TestSetPropertyHelper.alloc().init() 222 o.aSet = {1,2,3} 223 224 observer.register(o, 'aSet') 225 self.assertEquals(observer.seen, {}) 226 227 self.assertEquals(o.aSet - {2}, {1,3}) 228 self.assertEquals(o.aSet, {1,2,3}) 229 230 self.assertEquals(o.aSet | {4}, {1,2,3,4}) 231 self.assertEquals(o.aSet, {1,2,3}) 232 233 self.assertEquals(o.aSet & {3,4}, {3}) 234 self.assertEquals(o.aSet, {1,2,3}) 235 236 self.assertEquals(o.aSet ^ {3,4}, {1,2,4}) 237 self.assertEquals(o.aSet, {1,2,3}) 238 239 def testInplace(self): 240 # FIXME: the disabled lines in this test indicate a problem in 241 # either the set_proxy implementation, or my understanding of 242 # unordered collection properties. 243 with OCObserve.alloc().init() as observer: 244 o = TestSetPropertyHelper.alloc().init() 245 o.aSet.add(1) 246 observer.register(o, 'aSet') 247 248 249 # The inplace operators aren't actually implemented, which means 250 # "o.aSet |= value" is actually "o.aSet = o.aSet | value" and 251 # we get the some KVO notificatons as when a new value is set. 252 253 self.assertEqual(o.aSet, {1}) 254 o.aSet |= set([2,3]) 255 self.assertEqual(o.aSet, {1,2,3}) 256 self.assertEqual(o.aSet, set([1,2,3])) 257 self.assertEqual(len(observer.values), 2) 258 self.assertEqual(observer.values[-1][-1]['kind'], 1) 259 #self.assertEqual(observer.values[-1][-1]['old'], set([1])) 260 self.assertEqual(observer.values[-1][-1]['new'], set([1,2,3])) 261 262 self.assertEqual(o.aSet, {1,2,3}) 263 o.aSet &= set([3, 4]) 264 self.assertEqual(o.aSet, {3}) 265 self.assertEqual(o.aSet, set([3])) 266 self.assertEqual(len(observer.values), 4) 267 self.assertEqual(observer.values[-1][-1]['kind'], 1) 268 #self.assertEqual(observer.values[-1][-1]['old'], set([1,2,3])) 269 #self.assertEqual(observer.values[-1][-1]['new'], set([3])) 270 271 self.assertEqual(o.aSet, {3}) 272 o.aSet -= {3} 273 self.assertEqual(o.aSet, set()) 274 self.assertEqual(o.aSet, set([])) 275 self.assertEqual(len(observer.values), 6) 276 self.assertEqual(observer.values[-1][-1]['kind'], 1) 277 #self.assertEqual(observer.values[-1][-1]['old'], set([3])) 278 #self.assertEqual(observer.values[-1][-1]['new'], set()) 279 280 o.aSet = set([1,2,3]) 281 #self.assertEqual(len(observer.values), 8) 282 283 self.assertEqual(o.aSet, {1,2,3}) 284 o.aSet ^= set([1, 4]) 285 self.assertEqual(o.aSet, {2, 3, 4}) 286 #self.assertEqual(len(observer.values), 9) 287 self.assertEqual(observer.values[-1][-1]['kind'], 1) 288 #self.assertEqual(observer.values[-1][-1]['old'], set([1,2,3])) 289 #self.assertEqual(observer.values[-1][-1]['new'], set([2,3,4])) 290 291 def testObjCAccessors(self): 292 # Check that the right ObjC array accessors are defined and work properly 293 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"setASet:")) 294 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"aSet")) 295 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"countOfASet")) 296 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"enumeratorOfASet")) 297 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"memberOfASet:")) 298 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"addASet:")) 299 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"addASetObject:")) 300 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"removeASet:")) 301 self.assertTrue(TestSetPropertyHelper.instancesRespondToSelector_(b"removeASetObject:")) 302 303 o = TestSetPropertyHelper.alloc().init() 304 self.assertEqual(0, o.pyobjc_instanceMethods.countOfASet()) 305 self.assertRaises(AttributeError, getattr, o, 'countOfASet') 306 o.aSet.add(1) 307 o.aSet.add(2) 308 309 v = list(sorted(o.pyobjc_instanceMethods.enumeratorOfASet())) 310 self.assertEqual(v, [1,2]) 311 312 class Testing (object): 313 def __hash__(self): 314 return 42 315 316 def __eq__(self, other): 317 return isinstance(other, Testing) 318 319 p = Testing() 320 o.aSet.add(p) 321 322 v = o.pyobjc_instanceMethods.memberOfASet_(Testing()) 323 self.assertIs(p, v) 324 v = o.pyobjc_instanceMethods.memberOfASet_(9) 325 self.assertIs(v, None) 326 327 self.assertNotIn(9, o.aSet) 328 o.pyobjc_instanceMethods.addASet_(9) 329 self.assertIn(9, o.aSet) 330 331 self.assertNotIn(10, o.aSet) 332 o.pyobjc_instanceMethods.addASetObject_(10) 333 self.assertIn(10, o.aSet) 334 335 self.assertIn(9, o.aSet) 336 o.pyobjc_instanceMethods.removeASet_(9) 337 self.assertNotIn(9, o.aSet) 338 339 self.assertIn(10, o.aSet) 340 o.pyobjc_instanceMethods.removeASetObject_(10) 341 self.assertNotIn(10, o.aSet) 342 343 def test_ro_set(self): 344 o = TestSetPropertyHelper.alloc().init() 345 o._aROSet = { 1, 2, 3, 4 } 346 347 self.assertEqual(o.aROSet, { 1, 2, 3, 4 }) 348 self.assertIsNot(type(o.aROSet), set) 349 350 self.assertRaises(ValueError, o.aROSet.add, 1) 351 self.assertRaises(ValueError, o.aROSet.clear) 352 self.assertRaises(ValueError, o.aROSet.pop) 353 self.assertRaises(ValueError, o.aROSet.remove, 1) 354 self.assertRaises(ValueError, o.aROSet.difference_update, { 1, 2}) 355 self.assertRaises(ValueError, o.aROSet.intersection_update, { 1, 2}) 356 self.assertRaises(ValueError, o.aROSet.symmetric_difference_update, { 1, 2}) 357 self.assertRaises(ValueError, o.aROSet.update, { 1, 2}) 358 self.assertRaises(ValueError, o.aROSet.discard, 4) 359 360 try: 361 o.aROSet |= {1,2} 362 except ValueError: 363 pass 364 else: 365 self.fail() 366 367 try: 368 o.aROSet -= {1,2} 369 except ValueError: 370 pass 371 else: 372 self.fail() 373 374 try: 375 o.aROSet ^= {1,2} 376 except ValueError: 377 pass 378 else: 379 self.fail() 380 381 try: 382 o.aROSet &= {1,2} 383 except ValueError: 384 pass 385 else: 386 self.fail() 387 388 def test_compare(self): 389 o = TestSetPropertyHelper.alloc().init() 390 o.aSet = {1, 2, 3} 391 o.aSet2 = {1, 2, 3} 392 393 self.assertTrue(o.aSet == o.aSet2) 394 self.assertTrue(o.aSet == {1, 2, 3}) 395 self.assertTrue(o.aSet <= o.aSet2) 396 self.assertTrue(o.aSet <= {1, 2, 3}) 397 self.assertTrue(o.aSet >= o.aSet2) 398 self.assertTrue(o.aSet >= {1, 2, 3}) 399 self.assertFalse(o.aSet != o.aSet2) 400 self.assertFalse(o.aSet != {1, 2, 3}) 401 402 o.aSet2 = {2, 3} 403 self.assertTrue(o.aSet != o.aSet2) 404 self.assertTrue(o.aSet != {1, 2}) 405 self.assertFalse(o.aSet == o.aSet2) 406 self.assertFalse(o.aSet == {1, 2}) 407 408 o.aSet2 = { 1, 2, 3, 4} 409 self.assertTrue(o.aSet < o.aSet2) 410 self.assertTrue(o.aSet < {1, 2, 3, 4}) 411 self.assertTrue(o.aSet <= o.aSet2) 412 self.assertTrue(o.aSet <= {1, 2, 3, 4}) 413 self.assertFalse(o.aSet > o.aSet2) 414 self.assertFalse(o.aSet > {1, 2, 3, 4}) 415 self.assertFalse(o.aSet >= o.aSet2) 416 self.assertFalse(o.aSet >= {1, 2, 3, 4}) 417 418 o.aSet2 = { 1 } 419 self.assertTrue(o.aSet > o.aSet2) 420 self.assertTrue(o.aSet > {1}) 421 self.assertTrue(o.aSet >= o.aSet2) 422 self.assertTrue(o.aSet >= {1}) 423 self.assertFalse(o.aSet < o.aSet2) 424 self.assertFalse(o.aSet < {1}) 425 self.assertFalse(o.aSet <= o.aSet2) 426 self.assertFalse(o.aSet <= {1}) 427 428 if sys.version_info[0] == 2: 429 o.aSet = {1, 2, 3} 430 o.aSet2 = {1, 2 } 431 432 self.assertRaises(TypeError, cmp, o.aSet, o.aSet2) 433 #self.assertRaises(TypeError, cmp, o.aSet, {1}) 434 435 self.assertRaises(TypeError, o.aSet.__cmp__, o.aSet2) 436 self.assertRaises(TypeError, o.aSet.__cmp__, {1}) 437 438 def testPickling(self): 439 o = TestSetPropertyHelper.alloc().init() 440 o.aSet = {1, 2, 3} 441 442 self.assertFalse(isinstance(o.aSet, set)) 443 444 p = pickle.dumps(o.aSet) 445 v = pickle.loads(p) 446 self.assertEqual(o.aSet, v) 447 self.assertTrue(isinstance(v, set)) 448 449 450if __name__ == "__main__": 451 main() 452