1from PyObjCTools.TestSupport import * 2import objc 3from PyObjCTest.fnd import * 4 5objc.registerMetaDataForSelector( 6 b"NSObject", b"validateValue:forKey:error:", 7 dict( 8 arguments={ 9 2: dict(type_modifier=objc._C_INOUT), 10 4: dict(type_modifier=objc._C_OUT), 11 }, 12 )) 13 14 15class OCCopy (NSObject): 16 def copy(self): 17 return self.copyWithZone_(None) 18 19 def copyWithZone_(self, zone): 20 v = OCCopy.allocWithZone_(zone).init() 21 return v 22 23class OCObserve (NSObject): 24 def init(self): 25 self = super(OCObserve, self).init() 26 self.values = [] 27 self.registrations = [] 28 return self 29 30 def register(self, object, keypath): 31 object.addObserver_forKeyPath_options_context_( 32 self, keypath, 0x3, None) 33 self.registrations.append((object, keypath)) 34 35 def unregister(self, object, keypath): 36 object.removeObserver_forKeyPath_(self, keypath) 37 38 def observeValueForKeyPath_ofObject_change_context_( 39 self, keypath, object, change, context): 40 self.values.append((object, keypath, change)) 41 42 def __enter__(self): 43 return self 44 45 def __exit__(self, type, value, traceback): 46 for o, k in self.registrations: 47 self.unregister(o, k) 48 self.registrations = [] 49 50 51class TestObjectProperty (TestCase): 52 def testCreation(self): 53 class OCTestObjectProperty1 (NSObject): 54 p1 = objc.object_property() 55 p2 = objc.object_property(copy=True) 56 p3 = objc.object_property(read_only=True) 57 p4 = objc.object_property(ivar='myp4') 58 p5 = objc.object_property(typestr=objc._C_INT) 59 p6 = objc.object_property(typestr=objc._C_DBL) 60 61 62 o = OCTestObjectProperty1.alloc().init() 63 64 self.assertTrue(o.respondsToSelector(b'p1')) 65 self.assertTrue(o.respondsToSelector(b'setP1:')) 66 67 v = OCCopy.alloc().init() 68 o.p1 = v 69 self.assertIs(o.p1, v) 70 self.assertIs(o._p1, v) 71 72 self.assertTrue(o.respondsToSelector(b'p2')) 73 self.assertTrue(o.respondsToSelector(b'setP2:')) 74 75 o.p2 = v 76 self.assertIsInstance(o.p2, OCCopy) 77 self.assertIsNot(o.p2, v) 78 self.assertIsNot(o._p2, v) 79 80 self.assertTrue(o.respondsToSelector(b'p3')) 81 self.assertFalse(o.respondsToSelector(b'setP3:')) 82 83 o._p3 = v 84 self.assertIs(o.p3, v) 85 86 87 self.assertTrue(o.respondsToSelector(b'p4')) 88 self.assertTrue(o.respondsToSelector(b'setP4:')) 89 90 o.p4 = v 91 self.assertIs(o.p4, v) 92 self.assertIs(o.myp4, v) 93 94 self.assertTrue(o.respondsToSelector(b'p5')) 95 self.assertTrue(o.respondsToSelector(b'setP5:')) 96 self.assertTrue(o.respondsToSelector(b'p6')) 97 self.assertTrue(o.respondsToSelector(b'setP6:')) 98 s = o.methodSignatureForSelector_(b'p5') 99 self.assertEquals(s.methodReturnType(), objc._C_INT) 100 s = o.methodSignatureForSelector_(b'p6') 101 self.assertEquals(s.methodReturnType(), objc._C_DBL) 102 103 def testDepends(self): 104 class OCTestObjectProperty2 (NSObject): 105 p1 = objc.object_property() 106 p2 = objc.object_property() 107 p3 = objc.object_property(read_only=True, depends_on=['p1', 'p2']) 108 109 @p3.getter 110 def p3(self): 111 return (self.p1, self.p2) 112 113 observer = OCObserve.alloc().init() 114 object = OCTestObjectProperty2.alloc().init() 115 116 observer.register(object, 'p1') 117 observer.register(object, 'p2') 118 observer.register(object, 'p3') 119 try: 120 121 self.assertEquals(observer.values, []) 122 123 object.p1 = "a" 124 object.p2 = "b" 125 self.assertEquals(object.p3, ("a", "b")) 126 127 self.assertEquals(len(observer.values), 4) 128 129 if observer.values[0][1] == 'p1': 130 self.assertEquals(observer.values[1][1], 'p3') 131 else: 132 self.assertEquals(observer.values[0][1], 'p3') 133 self.assertEquals(observer.values[1][1], 'p1') 134 135 if observer.values[2][1] == 'p2': 136 self.assertEquals(observer.values[3][1], 'p3') 137 else: 138 self.assertEquals(observer.values[2][1], 'p3') 139 self.assertEquals(observer.values[3][1], 'p2') 140 141 finally: 142 observer.unregister(object, 'p1') 143 observer.unregister(object, 'p2') 144 observer.unregister(object, 'p3') 145 146 def testMethods(self): 147 l = [] 148 149 class OCTestObjectProperty4 (NSObject): 150 151 p1 = objc.object_property() 152 153 @p1.getter 154 def p1(self): 155 l.append(('get',)) 156 return self._p1 + '!' 157 158 @p1.setter 159 def p1(self, v): 160 l.append(('set', v)) 161 self._p1 = v + '?' 162 163 164 @p1.validate 165 def p1(self, value, error): 166 if value == 1: 167 return (True, value, None) 168 else: 169 return (False, 2, u"snake") 170 171 172 o = OCTestObjectProperty4.alloc().init() 173 o.p1 = 'f' 174 self.assertEquals(o.p1, 'f?!') 175 self.assertEquals(o._p1, 'f?') 176 self.assertEquals(l, [('set', 'f'), ('get',)]) 177 178 ok, value, error = o.validateValue_forKey_error_( 179 1, 'p1', None) 180 self.assertTrue(ok) 181 self.assertEquals(value, 1) 182 self.assertEquals(error, None) 183 184 ok, value, error = o.validateValue_forKey_error_( 185 9, 'p1', None) 186 self.assertFalse(ok) 187 self.assertEquals(value, 2) 188 self.assertEquals(error, u"snake") 189 190 def testNative(self): 191 l = [] 192 class OCTestObjectProperty7 (NSObject): 193 p1 = objc.object_property() 194 195 @p1.getter 196 def p1(self): 197 l.append('get') 198 return self._p1 199 200 @p1.setter 201 def p1(self, value): 202 l.append('set') 203 self._p1 = value 204 205 206 o = OCTestObjectProperty7.alloc().init() 207 o.setValue_forKey_(42, 'p1') 208 self.assertEquals(o._p1, 42) 209 210 o._p1 = u"monkey" 211 v = o.valueForKey_('p1') 212 self.assertEquals(v, u"monkey") 213 214 self.assertEquals(l, ["set", "get"]) 215 216 217 def testDynamic(self): 218 class OCTestObjectProperty8 (NSObject): 219 p1 = objc.object_property(dynamic=True) 220 221 self.assertFalse(OCTestObjectProperty8.instancesRespondToSelector_(b"p1")) 222 self.assertFalse(OCTestObjectProperty8.instancesRespondToSelector_(b"setP1:")) 223 224 v = [42] 225 def getter(self): 226 return v[0] 227 def setter(self, value): 228 v[0] = value 229 230 OCTestObjectProperty8.p1 = getter 231 OCTestObjectProperty8.setP1_ = setter 232 233 self.assertTrue(OCTestObjectProperty8.instancesRespondToSelector_(b"p1")) 234 self.assertTrue(OCTestObjectProperty8.instancesRespondToSelector_(b"setP1:")) 235 236 o = OCTestObjectProperty8.alloc().init() 237 self.assertIsInstance(OCTestObjectProperty8.p1, objc.object_property) 238 239 240 self.assertEquals(o.p1, 42) 241 o.p1 = 99 242 self.assertEquals(o.p1, 99) 243 self.assertEquals(v[0], 99) 244 245 246 def testReadOnly(self): 247 248 class OCTestObjectProperty3 (NSObject): 249 p1 = objc.object_property(read_only=True) 250 251 o = OCTestObjectProperty3.alloc().init() 252 253 self.assertRaises(ValueError, setattr, o, 'p1', 42) 254 255 def testSubclass(self): 256 257 class OCTestObjectProperty5 (NSObject): 258 p1 = objc.object_property(read_only=True) 259 p2 = objc.object_property() 260 261 class OCTestObjectProperty6 (OCTestObjectProperty5): 262 @OCTestObjectProperty5.p1.setter 263 def p1(self, value): 264 self._p1 = value 265 266 base = OCTestObjectProperty5.alloc().init() 267 self.assertRaises(ValueError, setattr, base, 'p1', 1) 268 base.p2 = 'b' 269 self.assertEquals(base.p2, 'b') 270 271 sub = OCTestObjectProperty6.alloc().init() 272 sub.p1 = 1 273 sub.p2 = 'a' 274 self.assertEquals(sub.p1, 1) 275 self.assertEquals(sub.p2, 'a') 276 277if __name__ == "__main__": 278 main() 279