1from PyObjCTools.TestSupport import * 2import objc 3 4setSignature = objc.setSignatureForSelector 5#setSignature(b"OCTestNULL", "callOut:", "i@:o^i") 6#setSignature(b"OCTestNULL", "callList:andInOut2:", "i@:@^i") 7#setSignature(b"OCTestNULL", "callList:andInOut:", "i@:@N^i") 8#setSignature(b"OCTestNULL", "callList:andIn:", "i@:@n^i") 9#setSignature(b"OCTestNULL", "callList:andOut:", "i@:@o^i") 10#setSignature(b"OCTestNULL", "on:callList:andInOut:", "i@:@@N^i") 11#setSignature(b"OCTestNULL", "on:callList:andIn:", "i@:@@n^i") 12#setSignature(b"OCTestNULL", "on:callList:andOut:", "i@:@@N^i") # 'N' is by design 13#setSignature(b"OCTestNULL", "on:callOut:", "v@:@N^i") # 'N' is by design 14 15objc.registerMetaDataForSelector(b"OCTestNULL", b"callOut:", dict( 16 arguments={ 17 2: dict(type_modifier=b'o', null_accepted=True), 18 }, 19 )) 20objc.registerMetaDataForSelector(b"OCTestNULL", b"callList:andInOut2:", dict( 21 arguments={ 22 3: dict(type_modifier=b'o', null_accepted=True), 23 }, 24 )) 25objc.registerMetaDataForSelector(b"OCTestNULL", b"callList:andInOut:", dict( 26 arguments={ 27 3: dict(type_modifier=b'N', null_accepted=True), 28 }, 29 )) 30objc.registerMetaDataForSelector(b"OCTestNULL", b"callList:andIn:", dict( 31 arguments={ 32 3: dict(type_modifier=b'n', null_accepted=True), 33 }, 34 )) 35objc.registerMetaDataForSelector(b"OCTestNULL", b"callList:andOut:", dict( 36 arguments={ 37 3: dict(type_modifier=b'o', null_accepted=True), 38 }, 39 )) 40objc.registerMetaDataForSelector(b"OCTestNULL", b"on:callList:andInOut:", dict( 41 arguments={ 42 4: dict(type_modifier=b'N', null_accepted=True), 43 }, 44 )) 45objc.registerMetaDataForSelector(b"OCTestNULL", b"on:callList:andIn:", dict( 46 arguments={ 47 4: dict(type_modifier=b'n', null_accepted=True), 48 }, 49 )) 50objc.registerMetaDataForSelector(b"OCTestNULL", b"on:callList:andOut:", dict( 51 arguments={ 52 4: dict(type_modifier=b'N', null_accepted=True), # N is by design 53 }, 54 )) 55objc.registerMetaDataForSelector(b"OCTestNULL", b"on:callOut:", dict( 56 arguments={ 57 3: dict(type_modifier=b'N', null_accepted=True), # N is by design 58 }, 59 )) 60 61from PyObjCTest.NULL import * 62 63class TestNULL (TestCase): 64 def testNULL(self): 65 self.assertHasAttr(objc, 'NULL') 66 self.assertEqual(repr(objc.NULL), 'objc.NULL') 67 self.assertRaises(TypeError, type(objc.NULL)) 68 69 70class TestNullArgumentsHelper (objc.lookUpClass("NSObject")): 71 72 def callList_andInOut_(self, lst, value): 73 lst.append(str(value)) 74 if value is objc.NULL: 75 return (13, value) 76 else: 77 return (13, value * 2) 78 79 callList_andInOut_ = objc.selector(callList_andInOut_, 80 signature=b"i@:@N^i") 81 82 def callList_andInOut2_(self, lst, value): 83 lst.append(repr(value)) 84 if value is objc.NULL: 85 return 29 86 else: 87 return 29 88 callList_andInOut2_ = objc.selector(callList_andInOut2_, 89 signature=b"i@:@^i") 90 91 def callList_andIn_(self, lst, value): 92 lst.append(repr(value)) 93 return 26 94 95 callList_andIn_ = objc.selector(callList_andIn_, 96 signature=b"i@:@n^i") 97 98 def callList_andOut_(self, lst, value): 99 assert value is None or value is objc.NULL 100 lst.append("Nothing here") 101 return (27, 99) 102 callList_andOut_ = objc.selector(callList_andOut_, 103 signature=b"i@:@o^i") 104 105 def callOut_(self, value): 106 assert value is None or value is objc.NULL 107 return 441; 108 callOut_ = objc.selector(callOut_, signature=b'v@:o^i') 109 110class TestNULLArguments (TestCase): 111 def testCallInOutNULL(self): 112 obj = OCTestNULL.alloc().init() 113 114 v = [] 115 rv = obj.callList_andInOut_(v, 42) 116 self.assertEqual(v, ["42"]) 117 self.assertEqual(rv, (12, 21)) 118 119 v = [] 120 rv = obj.callList_andInOut_(v, objc.NULL) 121 self.assertEqual(v, ["NULL"]) 122 self.assertEqual(rv, (12, objc.NULL)) 123 124 def testCallInOutNULL2(self): 125 # If nothing is specified the bridge assumes the argument behaves 126 # like an 'in' argument. 127 128 obj = OCTestNULL.alloc().init() 129 130 v = [] 131 self.assertRaises(ValueError, obj.callList_andInOut2_, v, 42) 132 self.assertEqual(v, []) 133 134 v = [] 135 rv = obj.callList_andInOut2_(v, objc.NULL) 136 self.assertEqual(v, ["NULL"]) 137 self.assertEqual(rv, (12, objc.NULL)) 138 139 def testCallInNULL(self): 140 obj = OCTestNULL.alloc().init() 141 142 v = [] 143 rv = obj.callList_andIn_(v, 42) 144 self.assertEqual(v, ["42"]) 145 self.assertEqual(rv, 24) 146 147 v = [] 148 rv = obj.callList_andIn_(v, objc.NULL) 149 self.assertEqual(v, ["NULL"]) 150 self.assertEqual(rv, 24) 151 152 153 def testCalledInOutNULL(self): 154 helper = OCTestNULL.alloc().init() 155 obj = TestNullArgumentsHelper.alloc().init() 156 157 v = [] 158 rv = helper.on_callList_andInOut_(obj, v, 42) 159 self.assertEqual(v, ['42']) 160 self.assertEqual(rv, (13, 84)) 161 162 v = [] 163 rv = helper.on_callList_andInOut_(obj, v, objc.NULL) 164 self.assertEqual(v, ['objc.NULL']) 165 self.assertEqual(rv, (13, objc.NULL)) 166 167 def testCalledInNULL(self): 168 helper = OCTestNULL.alloc().init() 169 obj = TestNullArgumentsHelper.alloc().init() 170 171 v = [] 172 rv = helper.on_callList_andIn_(obj, v, 42) 173 self.assertEqual(v, ['42']) 174 self.assertEqual(rv, 26) 175 176 v = [] 177 rv = helper.on_callList_andIn_(obj, v, objc.NULL) 178 self.assertEqual(v, ['objc.NULL']) 179 self.assertEqual(rv, 26) 180 181 def testCalledOutNULL(self): 182 183 helper = OCTestNULL.alloc().init() 184 obj = TestNullArgumentsHelper.alloc().init() 185 186 v = [] 187 rv = helper.on_callList_andOut_(obj, v, 42) 188 self.assertEqual(v, ['Nothing here']) 189 self.assertEqual(rv, (27, 99)) 190 191 v = [] 192 rv = helper.on_callList_andOut_(obj, v, objc.NULL) 193 self.assertEqual(v, ['Nothing here']) 194 self.assertEqual(rv, (27, objc.NULL)) 195 196 rv = helper.on_callOut_(obj, 42) 197 self.assertEqual(rv, 441) 198 199 rv = helper.on_callOut_(obj, objc.NULL) 200 self.assertEqual(rv, objc.NULL) 201 202 def dont_testCalledOutNULL(self): 203 """ 204 XXX: I'm not happy about these semantics! 205 206 Current semantics: called method doesn't know about the NULL argument, 207 the result from Python is ignored. 208 209 New semantics: 210 - If the last argument is 'out' use new semantics, otherwise keep 211 current semantics 212 - If function has an optional last param stuf this with objc.NULL if 213 the argument is NULL, otherwise don't provide 214 - If the functioin has a required last param: stuff with objc.NULL or 215 None 216 """ 217 218 219 def dont_testCallOutNULL(self): 220 """ 221 Call a method with an 'out' argument with an additional method 222 223 - if not objc.NULL: raise TypeError 224 - argument should be NULL in objC 225 - result should be objc.NULL 226 """ 227 228 229 230 231if __name__ == "__main__": 232 main() 233