1from PyObjCTools.TestSupport import * 2 3import objc 4import sys 5from PyObjCTest.instanceVariables import ClassWithVariables 6 7NSObject = objc.lookUpClass('NSObject') 8NSAutoreleasePool = objc.lookUpClass('NSAutoreleasePool') 9 10class Base (object): 11 def __init__(self, ondel): 12 self.ondel = ondel 13 14 def __del__ (self): 15 self.ondel() 16 17class OCBase (NSObject): 18 def init_(self, ondel): 19 self.ondel = ondel 20 21 def __del__ (self): 22 self.ondel() 23 24class TestClass (NSObject): 25 idVar = objc.ivar('idVar') 26 idVar2 = objc.ivar('idVar2', b'@') 27 intVar = objc.ivar('intVar', objc._C_INT) 28 doubleVar = objc.ivar('doubleVar', objc._C_DBL) 29 30 31class TestInstanceVariables(TestCase): 32 def setUp(self): 33 self.object = TestClass.alloc().init() 34 35 def testID(self): 36 # Check that we can set and query attributes of type 'id' 37 self.assertEquals(self.object.idVar, None) 38 self.assertEquals(self.object.idVar2, None) 39 40 o = NSObject.alloc().init() 41 42 self.object.idVar = o 43 self.object.idVar2 = o 44 45 self.assertIs(self.object.idVar, o) 46 self.assertIs(self.object.idVar2, o) 47 48 self.object.idVar = u"hello" 49 self.assertEquals(self.object.idVar, u"hello") 50 51 def testInt(self): 52 # Check that we can set and query attributes of type 'int' 53 self.assertEquals(self.object.intVar, 0) 54 55 self.assertRaises(ValueError, lambda x: setattr(self.object, 'intVar', x), "h") 56 57 self.object.intVar = 42 58 self.assertEquals(self.object.intVar, 42) 59 60 def testDouble(self): 61 # Check that we can set and query attributes of type 'double' 62 63 # Can't rely on this for doubles... 64 #self.assertEquals(self.object.doubleVar, 0.0) 65 self.assertRaises(ValueError, lambda x: setattr(self.object, 'doubleVar', x), u"h") 66 self.object.doubleVar = 42.0 67 self.assertAlmostEquals(self.object.doubleVar, 42.0) 68 69 def testLeak(self): 70 # Check that plain python objects are correctly released when 71 # they are no longer the value of an attribute 72 pool = NSAutoreleasePool.alloc().init() 73 self.deleted = 0 74 self.object.idVar = Base(lambda : setattr(self, 'deleted', 1)) 75 self.object.idVar = None 76 del pool 77 self.assertEquals(self.deleted, 1) 78 79 def testLeak2(self): 80 81 self.deleted = 0 82 83 pool = NSAutoreleasePool.alloc().init() 84 85 self.object.idVar = Base(lambda : setattr(self, 'deleted', 1)) 86 del self.object 87 del pool 88 self.assertEquals(self.deleted, 1) 89 90 def testOCLeak(self): 91 # Check that Objective-C objects are correctly released when 92 # they are no longer the value of an attribute 93 pool = NSAutoreleasePool.alloc().init() 94 self.deleted = 0 95 self.object.idVar = OCBase.alloc().init_(lambda : setattr(self, 'deleted', 1)) 96 self.object.idVar = None 97 del pool 98 self.assertEquals(self.deleted, 1) 99 100 def testOCLeak2(self): 101 pool = NSAutoreleasePool.alloc().init() 102 self.deleted = 0 103 self.object.idVar = OCBase.alloc().init_(lambda : setattr(self, 'deleted', 1)) 104 del self.object 105 del pool 106 self.assertEquals(self.deleted, 1) 107 108 def testDelete(self): 109 self.assertRaises(TypeError, delattr, self.object.idVar) 110 111 112class TestAllInstanceVariables (TestCase): 113 # Some tests for accessing any instance variable, even those not 114 # declared in python. 115 116 def testReading(self): 117 obj = ClassWithVariables.alloc().init() 118 119 getter = objc.getInstanceVariable 120 121 cls = getter(obj, 'isa') 122 self.assertIs(cls, type(obj)) 123 124 self.assertEquals(getter(obj, 'intValue'), 42) 125 self.assertIsInstance(getter(obj, 'intValue'), int) 126 127 self.assertEquals(getter(obj, 'floatValue'), -10.055) 128 self.assertIsInstance(getter(obj, 'floatValue'), float) 129 130 self.assertEquals(getter(obj, 'charValue'), ord('a')) 131 self.assertIsInstance(getter(obj, 'charValue'), int) 132 133 self.assertEquals(getter(obj, 'strValue'), b"hello world") 134 self.assertIsInstance(getter(obj, 'strValue'), bytes) 135 136 self.assertIsInstance(getter(obj, 'objValue'), NSObject) 137 138 self.assertIsNone(getter(obj, 'nilValue')) 139 140 self.assertEquals(getter(obj, 'pyValue'), slice(1, 10, 4)) 141 self.assertIsInstance(getter(obj, 'pyValue'), slice) 142 143 self.assertEquals(getter(obj, 'rectValue'), ((1, 2), (3, 4))) 144 145 self.assertRaises(AttributeError, getter, obj, "noSuchMember") 146 147 def testWriting(self): 148 obj = ClassWithVariables.alloc().init() 149 150 getter = objc.getInstanceVariable 151 setter = objc.setInstanceVariable 152 153 self.assertEquals(getter(obj, 'intValue'), 42) 154 setter(obj, 'intValue', 99) 155 self.assertEquals(getter(obj, 'intValue'), 99) 156 157 self.assertEquals(getter(obj, 'floatValue'), -10.055) 158 setter(obj, 'floatValue', 0.5) 159 self.assertEquals(getter(obj, 'floatValue'), 0.5) 160 161 self.assertEquals(getter(obj, 'charValue'), ord('a')) 162 setter(obj, 'charValue', b'b') 163 self.assertEquals(getter(obj, 'charValue'), ord('b')) 164 setter(obj, 'charValue', 10) 165 self.assertEquals(getter(obj, 'charValue'), 10) 166 167 self.assertEquals(getter(obj, 'strValue'), b"hello world") 168 setter(obj, 'strValue', b"foo bar") 169 self.assertEquals(getter(obj, 'strValue'), b"foo bar") 170 setter(obj, 'strValue', None) 171 self.assertEquals(getter(obj, 'strValue'), None) 172 173 o = NSObject.new() 174 self.assertIsNot(getter(obj, 'objValue'), o) 175 self.assertRaises(TypeError, setter, 'objValue', o) 176 self.assertIsNot(getter(obj, 'objValue'), o) 177 setter(obj, 'objValue', o, True) 178 self.assertIs(getter(obj, 'objValue'), o) 179 180 o2 = NSObject.new() 181 o2.retain() 182 self.assertIsNot(getter(obj, 'objValue'), o2) 183 setter(obj, 'objValue', o2, False) 184 self.assertIs(getter(obj, 'objValue'), o2) 185 186 self.assertEquals(getter(obj, 'pyValue'), slice(1, 10, 4)) 187 setter(obj, 'pyValue', [1,2,3]) 188 self.assertEquals(getter(obj, 'pyValue'), [1,2,3]) 189 190 self.assertEquals(getter(obj, 'rectValue'), ((1, 2), (3, 4))) 191 setter(obj, 'rectValue', ((-4, -8), (2, 7))) 192 self.assertEquals(getter(obj, 'rectValue'), ((-4, -8), (2, 7))) 193 194 self.assertRaises(AttributeError, setter, obj, "noSuchMember", 'foo') 195 196 def testClassMod(self): 197 # It's scary as hell, but updating the class of an object does "work" 198 # (for some perverted interpretation of the word) 199 200 class DummyClass (NSObject): 201 __slots__ = () 202 203 o = NSObject.alloc().init() 204 self.assertIsInstance(o, NSObject) 205 self.assertIsNotInstance(o, DummyClass) 206 207 objc.setInstanceVariable(o, "isa", DummyClass) 208 self.assertIsInstance(o, DummyClass) 209 210 def testDir(self): 211 obj = ClassWithVariables.alloc().init() 212 213 # Note: cannot check the exact contents of dir(), who knows 214 # what NSObject defines... 215 v = objc.listInstanceVariables(obj) 216 self.assertIn(('charValue', objc._C_CHR), v) 217 self.assertIn(('intValue', objc._C_INT), v) 218 self.assertIn(('isa', objc._C_CLASS), v) 219 220 221 def testAnonymousIvar(self): 222 223 class AnonIvarClass (NSObject): 224 225 var = objc.ivar() 226 var2 = objc.ivar(type=objc._C_DBL) 227 228 outlet = objc.IBOutlet() 229 230 o = AnonIvarClass.alloc().init() 231 o.var = NSObject.alloc().init() 232 233 self.assertIsInstance(o.var, NSObject) 234 235 o.var2 = 4 236 self.assertIsInstance(o.var2, float) 237 238 239if __name__ == '__main__': 240 main() 241