1""" 2Tests for the Key-Value Coding for hybrid python objects. 3 4NOTE: Testcases here should be synchronized with the Key-Value Coding tests 5in PyObjCTools.test.test_keyvalue and objc.test.test_keyvalue. 6 7TODO: 8 - This test uses C code, that code should be added to this package! 9 - Tests that access properties in the parent Objective-C class! 10 - More key-error tests, the tests don't cover all relevant code yet. 11""" 12import objc 13from PyObjCTools.TestSupport import * 14import sys 15from PyObjCTest.testhelper import PyObjC_TestClass3 as STUB 16from Foundation import * 17 18class KeyValueClass1 (NSObject): 19 def init(self): 20 self = super(KeyValueClass1, self).init() 21 self.key3 = 3 22 self._key4 = b"4".decode('ascii') 23 self.__private = b"private".decode('ascii') 24 return self 25 26 def addMultiple(self): 27 self.multiple = KeyValueClass1.alloc().init() 28 self.multiple.level2 = KeyValueClass1.alloc().init() 29 self.multiple.level2.level3 = KeyValueClass1.alloc().init() 30 self.multiple.level2.level3.keyA = b"hello".decode('ascii') 31 self.multiple.level2.level3.keyB = b"world".decode('ascii') 32 33 def getKey1(self): 34 return 1 35 36 def key2(self): 37 return 2 38 39 def setKey4_(self, value): 40 self._key4 = value * 4 41 42 def setKey5_(self, value): 43 self.key5 = value * 5 44 45 def keyRaisingValueError(self): 46 raise ValueError("42") 47 48 def keyRaisingNSUnknownKeyException(self): 49 return self.valueForKey_("thisKeyDoesNotExist") 50 51 def keyReturningSameSlector(self): 52 return self.keyReturningSameSelector 53 54 def keyReturningOtherSelector(self): 55 return self.getKey1 56 57class KeyValueClass1Explicit (NSObject): 58 def init(self): 59 self = super(KeyValueClass1Explicit, self).init() 60 self._values = {} 61 self._values[b'key3'.decode('ascii')] = 3 62 self._values[b'key4'.decode('ascii')] = b"4".decode('ascii') 63 self._values['_private'] = b"private".decode('ascii') 64 return self 65 66 def addMultiple(self): 67 self._values["multiple"] = KeyValueClass1Explicit.alloc().init() 68 self._values["multiple"]._values["level2"] = KeyValueClass1Explicit.alloc().init() 69 self._values["multiple"]._values["level2"]._values["level3"] = KeyValueClass1Explicit.alloc().init() 70 self._values["multiple"]._values["level2"]._values["level3"]._values["keyA"] = b"hello".decode('ascii') 71 self._values["multiple"]._values["level2"]._values["level3"]._values["keyB"] = b"world".decode('ascii') 72 73 def valueForKey_(self, key): 74 if key == "key1": 75 return 1 76 77 elif key == "key2": 78 return 2 79 80 return self._values[key] 81 82 def storedValueForKey_(self, key): 83 return self.valueForKey_(key) 84 85 def setValue_forKey_(self, value, key): 86 if key == "key4": 87 value = value * 4 88 elif key == "key5": 89 value = value * 5 90 91 self._values[key] = value 92 93 def takeStoredValue_forKey_(self, value, key): 94 self.setValue_forKey_(value, key) 95 96 def takeValue_forKey_(self, value, key): 97 self.setValue_forKey_(value, key) 98 99class KeyValueClass4 (NSObject): 100 __slots__ = ('foo', ) 101 102 def init(self): 103 self = super(KeyValueClass4, self).init() 104 self.foo = b"foobar".decode('ascii') 105 return self 106 107 # Definition for property 'bar'. Use odd names for the methods 108 # because the KeyValue support recognizes the usual names. 109 def read_bar(self): 110 return self.foo + self.foo 111 112 def write_bar (self, value): 113 self.foo = value + value 114 115 bar = property(read_bar, write_bar) 116 117 roprop = property(lambda self: b"read-only".decode('ascii')) 118 119class KVOClass(NSObject): 120 def automaticallyNotifiesObserversForKey_(self, aKey): 121 return objc.NO 122 123 def test(self): return b"test".decode('ascii') 124 125 126class KeyValueObserver (NSObject): 127 def init(self): 128 self.observed = [] 129 return self 130 131 def observeValueForKeyPath_ofObject_change_context_( 132 self, keyPath, object, change, context): 133 self.observed.append( (keyPath, object, change) ) 134 135 136class PyKeyValueCoding (TestCase): 137 def testNoPrivateVars(self): 138 # Private instance variables ('anObject.__value') are not accessible using 139 # key-value coding. 140 o = KeyValueClass1.alloc().init() 141 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 0, o, b"private".decode('ascii')) 142 143 def testValueForKey(self): 144 o = KeyValueClass1.alloc().init() 145 o.addMultiple() 146 147 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key1".decode('ascii')), 1) 148 149 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key2".decode('ascii')), 2) 150 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key3".decode('ascii')), 3) 151 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key4".decode('ascii')), "4") 152 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"multiple".decode('ascii')), o.multiple) 153 154 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 0, o, b"nokey".decode('ascii')) 155 156 self.assertRaises(ValueError, STUB.keyValue_forObject_key_, 0, o, 157 b"keyRaisingValueError".decode('ascii')) 158 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 0, o, 159 b"keyRaisingNSUnknownKeyException".decode('ascii')) 160 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 0, o, 161 b"keyReturningSameSelector".decode('ascii')) 162 163 obj = STUB.keyValue_forObject_key_( 0, o, b"keyReturningOtherSelector".decode('ascii')) 164 self.assertIsInstance(obj, objc.selector) 165 self.assertEqual(obj.selector, b"getKey1") 166 self.assertIs(obj.self, o ) 167 def testValueForKey2(self): 168 o = KeyValueClass4.alloc().init() 169 170 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"foo".decode('ascii')), b"foobar".decode('ascii')) 171 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"bar".decode('ascii')), b"foobarfoobar".decode('ascii')) 172 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"roprop".decode('ascii')), b"read-only".decode('ascii')) 173 174 175 def testStoredValueForKey(self): 176 o = KeyValueClass1.alloc().init() 177 o.addMultiple() 178 179 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key1".decode('ascii')), 1) 180 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key2".decode('ascii')), 2) 181 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key3".decode('ascii')), 3) 182 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key4".decode('ascii')), "4") 183 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"multiple".decode('ascii')), o.multiple) 184 185 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 2, o, b"nokey".decode('ascii')) 186 187 def testStoredValueForKey2(self): 188 o = KeyValueClass4.alloc().init() 189 190 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"foo".decode('ascii')), b"foobar".decode('ascii')) 191 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"bar".decode('ascii')), b"foobarfoobar".decode('ascii')) 192 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"roprop".decode('ascii')), b"read-only".decode('ascii')) 193 194 def testValueForKeyPath(self): 195 o = KeyValueClass1.alloc().init() 196 o.addMultiple() 197 198 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple".decode('ascii')), o.multiple) 199 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2".decode('ascii')), o.multiple.level2) 200 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2.level3.keyA".decode('ascii')), 201 o.multiple.level2.level3.keyA) 202 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2.level3.keyB".decode('ascii')), 203 o.multiple.level2.level3.keyB) 204 205 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 1, o, b"multiple.level2.nokey".decode('ascii')) 206 207 @max_os_level('10.5') 208 def testValuesForKeys(self): 209 o = KeyValueClass1.alloc().init() 210 211 self.assertEqual(STUB.keyValue_forObject_key_(3, o, [b"key1".decode('ascii'), b"key2".decode('ascii'), b"key3".decode('ascii'), b"key4".decode('ascii')]), { b"key1".decode('ascii'):1, b"key2".decode('ascii'):2, b"key3".decode('ascii'): 3, b"key4".decode('ascii'): b"4".decode('ascii')} ) 212 213 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 3, o, [b"key1".decode('ascii'), b"key3".decode('ascii'), b"nosuchkey".decode('ascii')]) 214 215 @max_os_level('10.5') 216 def testTakeValueForKey(self): 217 o = KeyValueClass1.alloc().init() 218 219 self.assertEqual(o.key3, 3) 220 STUB.setKeyValue_forObject_key_value_(0, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 221 self.assertEqual(o.key3, b"drie".decode('ascii')) 222 223 self.assertEqual(o._key4, b"4".decode('ascii')) 224 STUB.setKeyValue_forObject_key_value_(0, o, b'key4'.decode('ascii'), b'vier'.decode('ascii')) 225 self.assert_(not hasattr(o, b"key4".decode('ascii'))) 226 self.assertEqual(o._key4, b"viervierviervier".decode('ascii')) 227 228 o.key5 = 1 229 STUB.setKeyValue_forObject_key_value_(0, o, b'key5'.decode('ascii'), b'V'.decode('ascii')) 230 self.assertEqual(o.key5, b"VVVVV".decode('ascii')) 231 232 self.assert_(not hasattr(o, b'key9'.decode('ascii'))) 233 STUB.setKeyValue_forObject_key_value_(0, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 234 self.assert_(hasattr(o, b'key9'.decode('ascii'))) 235 self.assertEqual(o.key9, b'IX'.decode('ascii')) 236 237 @max_os_level('10.5') 238 def testTakeValueForKey2(self): 239 o = KeyValueClass4.alloc().init() 240 241 self.assertEqual(o.foo, b"foobar".decode('ascii')) 242 STUB.setKeyValue_forObject_key_value_(0, o, b'foo'.decode('ascii'), b'FOO'.decode('ascii')) 243 self.assertEqual(o.foo, b"FOO".decode('ascii')) 244 245 self.assertRaises(KeyError, STUB.setKeyValue_forObject_key_value_, 0, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 246 247 248 def testTakeStoredValueForKey(self): 249 o = KeyValueClass1.alloc().init() 250 251 self.assertEqual(o.key3, 3) 252 STUB.setKeyValue_forObject_key_value_(2, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 253 self.assertEqual(o.key3, b"drie".decode('ascii')) 254 255 self.assertEqual(o._key4, b"4".decode('ascii')) 256 STUB.setKeyValue_forObject_key_value_(2, o, b'key4'.decode('ascii'), b'vier'.decode('ascii')) 257 self.assertEqual(o._key4, b"viervierviervier".decode('ascii')) 258 259 o.key5 = 1 260 STUB.setKeyValue_forObject_key_value_(2, o, b'key5'.decode('ascii'), b'V'.decode('ascii')) 261 self.assertEqual(o.key5, b"VVVVV".decode('ascii')) 262 263 self.assert_(not hasattr(o, b'key9'.decode('ascii'))) 264 STUB.setKeyValue_forObject_key_value_(2, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 265 self.assert_(hasattr(o, b'key9'.decode('ascii'))) 266 self.assertEqual(o.key9, b'IX'.decode('ascii')) 267 268 def testStoredTakeValueForKey2(self): 269 o = KeyValueClass4.alloc().init() 270 271 self.assertEqual(o.foo, b"foobar".decode('ascii')) 272 STUB.setKeyValue_forObject_key_value_(2, o, b'foo'.decode('ascii'), b'FOO'.decode('ascii')) 273 self.assertEqual(o.foo, b"FOO".decode('ascii')) 274 275 self.assertRaises(KeyError, STUB.setKeyValue_forObject_key_value_, 2, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 276 self.assertRaises(KeyError, STUB.setKeyValue_forObject_key_value_, 2, o, b'roprop'.decode('ascii'), b'IX'.decode('ascii')) 277 278 @max_os_level('10.5') 279 def testTakeValuesFromDictionary(self): 280 o = KeyValueClass1.alloc().init() 281 282 self.assertEqual(o.key3, 3) 283 self.assertEqual(o._key4, b"4".decode('ascii')) 284 o.key5 = 1 285 self.assert_(not hasattr(o, b'key9'.decode('ascii'))) 286 287 STUB.setKeyValue_forObject_key_value_(3, o, None, 288 { 289 b'key3'.decode('ascii'): b'drie'.decode('ascii'), 290 b'key4'.decode('ascii'): b'vier'.decode('ascii'), 291 b'key5'.decode('ascii'): b'V'.decode('ascii'), 292 b'key9'.decode('ascii'): b'IX'.decode('ascii'), 293 }) 294 295 self.assertEqual(o.key3, b"drie".decode('ascii')) 296 self.assertEqual(o._key4, b"viervierviervier".decode('ascii')) 297 self.assertEqual(o.key5, b"VVVVV".decode('ascii')) 298 self.assert_(hasattr(o, b'key9'.decode('ascii'))) 299 self.assertEqual(o.key9, b'IX'.decode('ascii')) 300 301 @max_os_level('10.5') 302 def testTakeValuesFromDictionary2(self): 303 o = KeyValueClass4.alloc().init() 304 305 self.assertEqual(o.foo, b"foobar".decode('ascii')) 306 STUB.setKeyValue_forObject_key_value_(3, o, None, { b'foo'.decode('ascii'): b'FOO'.decode('ascii') }) 307 self.assertEqual(o.foo, b"FOO".decode('ascii')) 308 309 self.assertRaises(KeyError, STUB.setKeyValue_forObject_key_value_, 3, o, None, { b'key9'.decode('ascii'): b'IX'.decode('ascii') }) 310 self.assertRaises(KeyError, STUB.setKeyValue_forObject_key_value_, 3, o, None, { b'roprop'.decode('ascii'): b'IX'.decode('ascii') }) 311 312 @max_os_level('10.5') 313 def testTakeValueForKeyPath(self): 314 o = KeyValueClass1.alloc().init() 315 o.addMultiple() 316 317 self.assertEqual(o.multiple.level2.level3.keyA, b"hello".decode('ascii')) 318 self.assertEqual(o.multiple.level2.level3.keyB, b"world".decode('ascii')) 319 320 STUB.setKeyValue_forObject_key_value_(1, o, b"multiple.level2.level3.keyA".decode('ascii'), b"KeyAValue".decode('ascii')) 321 self.assertEqual(o.multiple.level2.level3.keyA, b"KeyAValue".decode('ascii')) 322 323 STUB.setKeyValue_forObject_key_value_(1, o, b"multiple.level2.level3.keyB".decode('ascii'), 9.999) 324 self.assertEqual(o.multiple.level2.level3.keyB, 9.999) 325 326 if hasattr(NSObject, b"willChangeValueForKey_".decode('ascii')): 327 # NSKeyValueObserving is only available on Panther and beyond 328 def testKVO1(self): 329 o = KVOClass.alloc().init() 330 o.addObserver_forKeyPath_options_context_(self, b"test".decode('ascii'), 0, None) 331 o.removeObserver_forKeyPath_(self, b"test".decode('ascii')) 332 333 def testKVO2(self): 334 """ 335 Check if observations work for python-based keys on ObjC classes 336 """ 337 observer = KeyValueObserver.alloc().init() 338 self.assertEqual(observer.observed, []) 339 340 o = KeyValueClass1.alloc().init() 341 342 o.addObserver_forKeyPath_options_context_(observer, b"key3".decode('ascii'), 0, 0) 343 try: 344 STUB.setKeyValue_forObject_key_value_(2, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 345 self.assertEqual(o.key3, b"drie".decode('ascii')) 346 347 self.assertEqual(len(observer.observed), 1) 348 349 keyPath, object, change = observer.observed[0] 350 self.assertEqual(keyPath, b"key3".decode('ascii')) 351 self.assert_(object is o) 352 self.assertEqual(change, {NSKeyValueChangeKindKey: 1 }) 353 354 finally: 355 o.removeObserver_forKeyPath_(observer, b'key3'.decode('ascii')) 356 357 def testKVO3(self): 358 """ 359 Check if observations work for python-based keys on ObjC classes 360 """ 361 observer = KeyValueObserver.alloc().init() 362 self.assertEqual(observer.observed, []) 363 364 o = KeyValueClass1.alloc().init() 365 STUB.setKeyValue_forObject_key_value_(2, o, b'key3'.decode('ascii'), b'three'.decode('ascii')) 366 367 o.addObserver_forKeyPath_options_context_(observer, b"key3".decode('ascii'), 368 NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld, 369 0) 370 try: 371 STUB.setKeyValue_forObject_key_value_(2, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 372 self.assertEqual(o.key3, b"drie".decode('ascii')) 373 374 self.assertEqual(len(observer.observed), 1) 375 376 keyPath, object, change = observer.observed[0] 377 self.assertEqual(keyPath, b"key3".decode('ascii')) 378 self.assert_(object is o) 379 self.assertEqual(change, 380 { 381 NSKeyValueChangeKindKey:1, 382 NSKeyValueChangeNewKey:b'drie'.decode('ascii'), 383 NSKeyValueChangeOldKey:b'three'.decode('ascii') 384 }) 385 386 finally: 387 o.removeObserver_forKeyPath_(observer, b'key3'.decode('ascii')) 388 389class PyKeyValueCodingExplicit (TestCase): 390 391 def testValueForKey(self): 392 o = KeyValueClass1Explicit.alloc().init() 393 o.addMultiple() 394 395 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key1".decode('ascii')), 1) 396 397 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key2".decode('ascii')), 2) 398 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key3".decode('ascii')), 3) 399 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"key4".decode('ascii')), "4") 400 self.assertEqual(STUB.keyValue_forObject_key_(0, o, b"multiple".decode('ascii')), o._values['multiple']) 401 402 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 0, o, b"nokey".decode('ascii')) 403 404 def testStoredValueForKey(self): 405 o = KeyValueClass1Explicit.alloc().init() 406 o.addMultiple() 407 408 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key1".decode('ascii')), 1) 409 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key2".decode('ascii')), 2) 410 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key3".decode('ascii')), 3) 411 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"key4".decode('ascii')), "4") 412 self.assertEqual(STUB.keyValue_forObject_key_(2, o, b"multiple".decode('ascii')), o._values['multiple']) 413 414 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 2, o, b"nokey".decode('ascii')) 415 416 def testValueForKeyPath(self): 417 o = KeyValueClass1Explicit.alloc().init() 418 o.addMultiple() 419 420 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple".decode('ascii')), o._values['multiple']) 421 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2".decode('ascii')), o._values['multiple']._values['level2']) 422 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2.level3.keyA".decode('ascii')), 423 o._values['multiple']._values['level2']._values['level3']._values['keyA']) 424 self.assertEqual(STUB.keyValue_forObject_key_(1, o, b"multiple.level2.level3.keyB".decode('ascii')), 425 o._values['multiple']._values['level2']._values['level3']._values['keyB']) 426 427 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 1, o, b"multiple.level2.nokey".decode('ascii')) 428 429 @max_os_level('10.5') 430 def testValuesForKeys(self): 431 o = KeyValueClass1Explicit.alloc().init() 432 433 self.assertEqual(STUB.keyValue_forObject_key_(3, o, [b"key1".decode('ascii'), b"key2".decode('ascii'), b"key3".decode('ascii'), b"key4".decode('ascii')]), { b"key1".decode('ascii'):1, b"key2".decode('ascii'):2, b"key3".decode('ascii'): 3, b"key4".decode('ascii'): b"4".decode('ascii')} ) 434 435 self.assertRaises(KeyError, STUB.keyValue_forObject_key_, 3, o, [b"key1".decode('ascii'), b"key3".decode('ascii'), b"nosuchkey".decode('ascii')]) 436 437 def testTakeValueForKey(self): 438 o = KeyValueClass1Explicit.alloc().init() 439 440 self.assertEqual(o._values['key3'], 3) 441 STUB.setKeyValue_forObject_key_value_(0, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 442 self.assertEqual(o._values['key3'], b"drie".decode('ascii')) 443 444 self.assertEqual(o._values['key4'], b"4".decode('ascii')) 445 STUB.setKeyValue_forObject_key_value_(0, o, b'key4'.decode('ascii'), b'vier'.decode('ascii')) 446 self.assert_(not hasattr(o, b"key4".decode('ascii'))) 447 self.assertEqual(o._values['key4'], b"viervierviervier".decode('ascii')) 448 449 o._values['key5'] = 1 450 STUB.setKeyValue_forObject_key_value_(0, o, b'key5'.decode('ascii'), b'V'.decode('ascii')) 451 self.assertEqual(o._values['key5'], b"VVVVV".decode('ascii')) 452 453 self.assert_(not hasattr(o, b'key9'.decode('ascii'))) 454 self.assert_('key9' not in o._values) 455 STUB.setKeyValue_forObject_key_value_(0, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 456 self.assert_(not hasattr(o, b'key9'.decode('ascii'))) 457 self.assert_('key9' in o._values) 458 self.assertEqual(o._values['key9'], b'IX'.decode('ascii')) 459 460 def testTakeStoredValueForKey(self): 461 o = KeyValueClass1Explicit.alloc().init() 462 463 self.assertEqual(o._values['key3'], 3) 464 STUB.setKeyValue_forObject_key_value_(2, o, b'key3'.decode('ascii'), b'drie'.decode('ascii')) 465 self.assertEqual(o._values['key3'], b"drie".decode('ascii')) 466 467 self.assertEqual(o._values['key4'], b"4".decode('ascii')) 468 STUB.setKeyValue_forObject_key_value_(2, o, b'key4'.decode('ascii'), b'vier'.decode('ascii')) 469 self.assertEqual(o._values['key4'], b"viervierviervier".decode('ascii')) 470 471 o.key5 = 1 472 STUB.setKeyValue_forObject_key_value_(2, o, b'key5'.decode('ascii'), b'V'.decode('ascii')) 473 self.assertEqual(o._values['key5'], b"VVVVV".decode('ascii')) 474 475 self.assert_('key9' not in o._values) 476 STUB.setKeyValue_forObject_key_value_(2, o, b'key9'.decode('ascii'), b'IX'.decode('ascii')) 477 self.assert_('key9' in o._values) 478 self.assertEqual(o._values['key9'], b'IX'.decode('ascii')) 479 480 @max_os_level('10.5') 481 def testTakeValuesFromDictionary(self): 482 o = KeyValueClass1Explicit.alloc().init() 483 484 self.assertEqual(o._values['key3'], 3) 485 self.assertEqual(o._values['key4'], b"4".decode('ascii')) 486 o._values['key5'] = 1 487 self.assert_('key9' not in o._values) 488 489 STUB.setKeyValue_forObject_key_value_(3, o, None, 490 { 491 b'key3'.decode('ascii'): b'drie'.decode('ascii'), 492 b'key4'.decode('ascii'): b'vier'.decode('ascii'), 493 b'key5'.decode('ascii'): b'V'.decode('ascii'), 494 b'key9'.decode('ascii'): b'IX'.decode('ascii'), 495 }) 496 497 self.assertEqual(o._values['key3'], b"drie".decode('ascii')) 498 self.assertEqual(o._values['key4'], b"viervierviervier".decode('ascii')) 499 self.assertEqual(o._values['key5'], b"VVVVV".decode('ascii')) 500 self.assertEqual(o._values['key9'], b'IX'.decode('ascii')) 501 502 @max_os_level('10.5') 503 def testTakeValueForKeyPath(self): 504 o = KeyValueClass1Explicit.alloc().init() 505 o.addMultiple() 506 507 self.assertEqual(o._values['multiple']._values['level2']._values['level3']._values['keyA'], b"hello".decode('ascii')) 508 self.assertEqual(o._values['multiple']._values['level2']._values['level3']._values['keyB'], b"world".decode('ascii')) 509 510 STUB.setKeyValue_forObject_key_value_(1, o, b"multiple.level2.level3.keyA".decode('ascii'), b"KeyAValue".decode('ascii')) 511 self.assertEqual(o._values['multiple']._values['level2']._values['level3']._values['keyA'], b"KeyAValue".decode('ascii')) 512 513 STUB.setKeyValue_forObject_key_value_(1, o, b"multiple.level2.level3.keyB".decode('ascii'), 9.999) 514 self.assertEqual(o._values['multiple']._values['level2']._values['level3']._values['keyB'], 9.999) 515 516 517class TestBaseExceptions (TestCase): 518 """ 519 Check that NSObject implementation of Key-Value coding raises the 520 exception that we expect it to raise. 521 """ 522 def testValueForKey(self): 523 o = NSObject.alloc().init() 524 525 self.assertRaises(KeyError, o.valueForKey_, b"unknownKey".decode('ascii')) 526 527 def testStoredValueForKey(self): 528 o = NSObject.alloc().init() 529 530 self.assertRaises(KeyError, o.storedValueForKey_, b"unknownKey".decode('ascii')) 531 532 def testTakeStoredValue(self): 533 o = NSObject.alloc().init() 534 535 self.assertRaises(KeyError, 536 o.takeStoredValue_forKey_, b"value".decode('ascii'), b"unknownKey".decode('ascii')) 537 538 539 540if __name__ == "__main__": 541 main() 542