1from PyObjCTools.TestSupport import * 2 3import objc 4import sys 5 6try: 7 from Foundation import NSRange 8 9 _C_NSRange = NSRange.__typestr__ 10 11except ImportError: 12 if sys.maxsize > 2 ** 32: 13 _C_NSRange = b"{_NSRange=QQ}" 14 else: 15 _C_NSRange = b"{_NSRange=II}" 16 17 18NSObject = objc.lookUpClass("NSObject") 19 20class TestBasicDescriptors (TestCase): 21 22 # IBOutlet is tested in test_ivar 23 24 def test_ibaction(self): 25 26 @objc.IBAction 27 def myAction_(self, sender): 28 return 1 29 30 self.assertIsInstance(myAction_, objc.selector) 31 self.assertEqual(myAction_.signature, b'v@:@') 32 self.assertEqual(myAction_.selector, b'myAction:') 33 self.assertFalse(myAction_.isClassMethod) 34 35 36 self.assertRaises(TypeError, objc.IBAction, None) 37 self.assertRaises(TypeError, objc.IBAction, 42) 38 39 def test_instancemethod(self): 40 class TestDescriptorsClass1 (NSObject): 41 @objc.instancemethod 42 def new(self): 43 pass 44 45 o = NSObject.alloc().init() 46 self.assertFalse(hasattr(o, 'new')) 47 self.assertTrue(hasattr(NSObject, 'new')) 48 self.assertTrue(NSObject.new.isClassMethod) 49 50 o = TestDescriptorsClass1.alloc().init() 51 m = o.new 52 self.assertIsInstance(m, objc.selector) 53 self.assertFalse(m.isClassMethod) 54 55 56 self.assertRaises(TypeError, objc.instancemethod, None) 57 self.assertRaises(TypeError, objc.instancemethod, 42) 58 59 def test_typedSelector(self): 60 61 @objc.typedSelector(b"I@:qq") 62 def mySelector_arg_(self, a, b): 63 return 4 64 65 self.assertIsInstance(mySelector_arg_, objc.selector) 66 self.assertEqual(mySelector_arg_.signature, b"I@:qq") 67 self.assertEqual(mySelector_arg_.selector, b"mySelector:arg:") 68 69 self.assertRaises(TypeError, objc.typedSelector(b"v@:i"), None) 70 self.assertRaises(TypeError, objc.typedSelector(b"v@:i"), 42) 71 72 def testNamedSelector(self): 73 @objc.namedSelector(b'foo:bar:') 74 def mymethod(self, a, b): 75 pass 76 77 self.assertIsInstance(mymethod, objc.selector) 78 self.assertEqual(mymethod.signature, b"v@:@@") 79 self.assertEqual(mymethod.selector, b"foo:bar:") 80 81 self.assertRaises(TypeError, objc.namedSelector(b"foo:bar:"), None) 82 self.assertRaises(TypeError, objc.namedSelector(b"foo:bar:"), 42) 83 84 @objc.namedSelector(b'foo:bar:', signature=b"q@:qq") 85 def mymethod(self, a, b): 86 pass 87 88 self.assertIsInstance(mymethod, objc.selector) 89 self.assertEqual(mymethod.signature, b"q@:qq") 90 self.assertEqual(mymethod.selector, b"foo:bar:") 91 92 self.assertRaises(TypeError, objc.namedSelector(b"foo:bar:", b"q@:qq"), None) 93 self.assertRaises(TypeError, objc.namedSelector(b"foo:bar:", b"q@:qq"), 42) 94 95 def testNamedselector(self): 96 with filterWarnings("ignore", RuntimeWarning): 97 @objc.namedselector(b'foo:bar:') 98 def mymethod(self, a, b): 99 pass 100 101 self.assertIsInstance(mymethod, objc.selector) 102 self.assertEqual(mymethod.signature, b"v@:@@") 103 self.assertEqual(mymethod.selector, b"foo:bar:") 104 105 self.assertRaises(TypeError, objc.namedselector(b"foo:bar:"), None) 106 self.assertRaises(TypeError, objc.namedselector(b"foo:bar:"), 42) 107 108 @objc.namedselector(b'foo:bar:', signature=b"q@:qq") 109 def mymethod(self, a, b): 110 pass 111 112 self.assertIsInstance(mymethod, objc.selector) 113 self.assertEqual(mymethod.signature, b"q@:qq") 114 self.assertEqual(mymethod.selector, b"foo:bar:") 115 116 self.assertRaises(TypeError, objc.namedselector(b"foo:bar:", b"q@:qq"), None) 117 self.assertRaises(TypeError, objc.namedselector(b"foo:bar:", b"q@:qq"), 42) 118 119 # synthesize is tested in test_synthesize 120 121 def test_accessor(self): 122 # NOTE: the optional type argument is tested through the typedAccessor function 123 124 # Basic properties: 125 126 @objc.accessor 127 def color(self): 128 return 42 129 130 @objc.accessor 131 def isColor(self): 132 return 42 133 134 @objc.accessor 135 def setColor_(self, value): 136 pass 137 138 self.assertIsInstance(color, objc.selector) 139 self.assertIsInstance(isColor, objc.selector) 140 self.assertIsInstance(setColor_, objc.selector) 141 142 self.assertEqual(color.signature, b"@@:") 143 self.assertEqual(isColor.signature, b"@@:") 144 self.assertEqual(setColor_.signature, b"v@:@") 145 146 147 # Indexed accessors 148 149 @objc.accessor 150 def countOfFlavors(self): 151 return 2 152 153 @objc.accessor 154 def objectInFlavorsAtIndex_(self, idx): 155 return "sour" 156 157 @objc.accessor 158 def flavorsAtIndexes_(sef, indices): 159 return ["sour", "sweet"] 160 161 @objc.accessor 162 def getFlavors_range_(self, buffer, range): 163 return ["sour", "sweet"] 164 165 166 self.assertIsInstance(countOfFlavors, objc.selector) 167 self.assertIsInstance(objectInFlavorsAtIndex_, objc.selector) 168 self.assertIsInstance(flavorsAtIndexes_, objc.selector) 169 self.assertIsInstance(getFlavors_range_, objc.selector) 170 171 self.assertEqual(countOfFlavors.signature, objc._C_NSUInteger + b"@:") 172 self.assertEqual(objectInFlavorsAtIndex_.signature, b"@@:" + objc._C_NSUInteger) 173 self.assertEqual(flavorsAtIndexes_.signature, b"@@:@") 174 175 # XXX: This needs even more work: also have to add custom metadata! 176 self.assertEqual(getFlavors_range_.signature, b"v@:o^@" + _C_NSRange) 177 178 # Mutable Indexed Accessors 179 180 @objc.accessor 181 def insertObject_inFlavorsAtIndex_(self, value, idx): 182 pass 183 184 @objc.accessor 185 def insertFlavors_atIndexes_(self, values, indices): 186 pass 187 188 @objc.accessor 189 def removeObjectFromFlavorsAtIndex_(self, index): 190 pass 191 192 @objc.accessor 193 def removeFlavorsAtIndexes_(self, indices): 194 pass 195 196 @objc.accessor 197 def replaceObjectInFlavorsAtIndex_withObject_(self, value, idx): 198 pass 199 200 @objc.accessor 201 def replaceFlavorsAtIndexes_withFlavors_(self, indices, values): 202 pass 203 204 205 self.assertIsInstance(insertObject_inFlavorsAtIndex_, objc.selector) 206 self.assertIsInstance(insertFlavors_atIndexes_, objc.selector) 207 self.assertIsInstance(removeObjectFromFlavorsAtIndex_, objc.selector) 208 self.assertIsInstance(removeFlavorsAtIndexes_, objc.selector) 209 self.assertIsInstance(replaceObjectInFlavorsAtIndex_withObject_, objc.selector) 210 self.assertIsInstance(replaceFlavorsAtIndexes_withFlavors_, objc.selector) 211 212 self.assertEqual(insertObject_inFlavorsAtIndex_.signature, b"v@:@" + objc._C_NSUInteger) 213 self.assertEqual(insertFlavors_atIndexes_.signature, b"v@:@@") 214 self.assertEqual(removeObjectFromFlavorsAtIndex_.signature, b"v@:" + objc._C_NSUInteger) 215 self.assertEqual(removeFlavorsAtIndexes_.signature, b"v@:@") 216 self.assertEqual(replaceObjectInFlavorsAtIndex_withObject_.signature, b"v@:" + objc._C_NSUInteger + b"@") 217 self.assertEqual(replaceFlavorsAtIndexes_withFlavors_.signature, b"v@:@@") 218 219 220 # Getter Unordered Accessors 221 @objc.accessor 222 def countOfLanguages(self): 223 pass 224 225 @objc.accessor 226 def enumeratorOfLanguages(self): 227 pass 228 229 @objc.accessor 230 def memberOfLanguages_(self, value): 231 return False 232 233 self.assertIsInstance(countOfLanguages, objc.selector) 234 self.assertIsInstance(enumeratorOfLanguages, objc.selector) 235 self.assertIsInstance(memberOfLanguages_, objc.selector) 236 237 self.assertEqual(countOfLanguages.signature, objc._C_NSUInteger + b"@:") 238 self.assertEqual(enumeratorOfLanguages.signature, b"@@:") 239 self.assertEqual(memberOfLanguages_.signature, objc._C_NSBOOL + b"@:@") 240 241 # Mutable Unordered Accessors 242 243 @objc.accessor 244 def addLanguagesObject_(self, value): 245 pass 246 247 @objc.accessor 248 def addLanguagues_(self, values): 249 pass 250 251 @objc.accessor 252 def intersectLanguagues_(self, values): 253 pass 254 255 self.assertIsInstance(addLanguagesObject_, objc.selector) 256 self.assertIsInstance(addLanguagues_, objc.selector) 257 self.assertIsInstance(intersectLanguagues_, objc.selector) 258 259 self.assertEqual(addLanguagesObject_.signature, b"v@:@") 260 self.assertEqual(addLanguagues_.signature, b"v@:@") 261 self.assertEqual(intersectLanguagues_.signature, b"v@:@") 262 263 # Validation 264 @objc.accessor 265 def validateColor_error_(self, value, error): 266 return (False, None) 267 268 self.assertIsInstance(validateColor_error_, objc.selector) 269 self.assertEqual(validateColor_error_.signature, objc._C_NSBOOL + b'@:N^@o^@') 270 271 272 273 # Keyword arguments (**kwds) and varargs (*args) are 274 # not supported: 275 276 def attrib(self, *args): 277 pass 278 self.assertRaises(TypeError, objc.accessor, attrib) 279 280 def attrib(self, **kwds): 281 pass 282 self.assertRaises(TypeError, objc.accessor, attrib) 283 284 # Not really an accessor 285 def attrib_error_(self, a, b): 286 pass 287 self.assertRaises(TypeError, objc.accessor, attrib_error_) 288 289 # Argument counts that don't match 290 def validateObject_error_(self, a): 291 pass 292 self.assertRaises(TypeError, objc.accessor, validateObject_error_) 293 294 def validateObject_error_(self, a, b, c): 295 pass 296 self.assertRaises(TypeError, objc.accessor, validateObject_error_) 297 298 def validateObject_error_(self, a, b, c, d=1, e=2): 299 pass 300 self.assertRaises(TypeError, objc.accessor, validateObject_error_) 301 302 @objc.accessor 303 def validateObject_error_(self, a, b, c=1): 304 pass 305 306 307 308 309 def test_typedAccessor(self): 310 # NOTE: the optional type argument is tested through the typedAccessor function 311 312 # Basic properties: 313 314 mytype = b"{Struct=qq}" 315 316 @objc.typedAccessor(mytype) 317 def color(self): 318 return 42 319 320 @objc.typedAccessor(mytype) 321 def isColor(self): 322 return 42 323 324 @objc.typedAccessor(mytype) 325 def setColor_(self, value): 326 pass 327 328 self.assertIsInstance(color, objc.selector) 329 self.assertIsInstance(isColor, objc.selector) 330 self.assertIsInstance(setColor_, objc.selector) 331 332 self.assertEqual(color.signature, mytype + b"@:") 333 self.assertEqual(isColor.signature, mytype + b"@:") 334 self.assertEqual(setColor_.signature, b"v@:" + mytype) 335 336 337 # Indexed accessors 338 339 @objc.typedAccessor(mytype) 340 def countOfFlavors(self): 341 return 2 342 343 @objc.typedAccessor(mytype) 344 def objectInFlavorsAtIndex_(self, idx): 345 return "sour" 346 347 @objc.typedAccessor(mytype) 348 def flavorsAtIndexes_(sef, indices): 349 return ["sour", "sweet"] 350 351 @objc.typedAccessor(mytype) 352 def getFlavors_range_(self, buffer, range): 353 return ["sour", "sweet"] 354 355 356 self.assertIsInstance(countOfFlavors, objc.selector) 357 self.assertIsInstance(objectInFlavorsAtIndex_, objc.selector) 358 self.assertIsInstance(flavorsAtIndexes_, objc.selector) 359 self.assertIsInstance(getFlavors_range_, objc.selector) 360 361 self.assertEqual(countOfFlavors.signature, objc._C_NSUInteger + b"@:") 362 self.assertEqual(objectInFlavorsAtIndex_.signature, mytype + b"@:" + objc._C_NSUInteger) 363 self.assertEqual(flavorsAtIndexes_.signature, b"@@:@") #XXX: is this correct? 364 365 # XXX: This needs even more work: also have to add custom metadata! 366 self.assertEqual(getFlavors_range_.signature, b"v@:o^@" + _C_NSRange) 367 368 # Mutable Indexed Accessors 369 370 @objc.typedAccessor(mytype) 371 def insertObject_inFlavorsAtIndex_(self, value, idx): 372 pass 373 374 @objc.typedAccessor(mytype) 375 def insertFlavors_atIndexes_(self, values, indices): 376 pass 377 378 @objc.typedAccessor(mytype) 379 def removeObjectFromFlavorsAtIndex_(self, index): 380 pass 381 382 @objc.typedAccessor(mytype) 383 def removeFlavorsAtIndexes_(self, indices): 384 pass 385 386 @objc.typedAccessor(mytype) 387 def replaceObjectInFlavorsAtIndex_withObject_(self, value, idx): 388 pass 389 390 @objc.typedAccessor(mytype) 391 def replaceFlavorsAtIndexes_withFlavors_(self, indices, values): 392 pass 393 394 395 self.assertIsInstance(insertObject_inFlavorsAtIndex_, objc.selector) 396 self.assertIsInstance(insertFlavors_atIndexes_, objc.selector) 397 self.assertIsInstance(removeObjectFromFlavorsAtIndex_, objc.selector) 398 self.assertIsInstance(removeFlavorsAtIndexes_, objc.selector) 399 self.assertIsInstance(replaceObjectInFlavorsAtIndex_withObject_, objc.selector) 400 self.assertIsInstance(replaceFlavorsAtIndexes_withFlavors_, objc.selector) 401 402 self.assertEqual(insertObject_inFlavorsAtIndex_.signature, b"v@:" + mytype + objc._C_NSUInteger) 403 self.assertEqual(insertFlavors_atIndexes_.signature, b"v@:@@") # XXX: is this correct? 404 self.assertEqual(removeObjectFromFlavorsAtIndex_.signature, b"v@:" + objc._C_NSUInteger) 405 self.assertEqual(removeFlavorsAtIndexes_.signature, b"v@:@") 406 self.assertEqual(replaceObjectInFlavorsAtIndex_withObject_.signature, b"v@:" + objc._C_NSUInteger + mytype) 407 self.assertEqual(replaceFlavorsAtIndexes_withFlavors_.signature, b"v@:@@") # XXX: is this correct? 408 409 410 # Getter Unordered Accessors 411 @objc.typedAccessor(mytype) 412 def countOfLanguages(self): 413 pass 414 415 @objc.typedAccessor(mytype) 416 def enumeratorOfLanguages(self): 417 pass 418 419 @objc.typedAccessor(mytype) 420 def memberOfLanguages_(self, value): 421 return False 422 423 self.assertIsInstance(countOfLanguages, objc.selector) 424 self.assertIsInstance(enumeratorOfLanguages, objc.selector) 425 self.assertIsInstance(memberOfLanguages_, objc.selector) 426 427 self.assertEqual(countOfLanguages.signature, objc._C_NSUInteger + b"@:") 428 self.assertEqual(enumeratorOfLanguages.signature, b"@@:") 429 self.assertEqual(memberOfLanguages_.signature, objc._C_NSBOOL + b"@:" + mytype) 430 431 # Mutable Unordered Accessors 432 433 @objc.typedAccessor(mytype) 434 def addLanguagesObject_(self, value): 435 pass 436 437 @objc.typedAccessor(mytype) 438 def addLanguagues_(self, values): 439 pass 440 441 @objc.typedAccessor(mytype) 442 def intersectLanguagues_(self, values): 443 pass 444 445 self.assertIsInstance(addLanguagesObject_, objc.selector) 446 self.assertIsInstance(addLanguagues_, objc.selector) 447 self.assertIsInstance(intersectLanguagues_, objc.selector) 448 449 self.assertEqual(addLanguagesObject_.signature, b"v@:" + mytype) 450 self.assertEqual(addLanguagues_.signature, b"v@:@") # XXX: is this correct? 451 self.assertEqual(intersectLanguagues_.signature, b"v@:@") 452 453 # Validation 454 @objc.typedAccessor(mytype) 455 def validateColor_error_(self, value, error): 456 return (False, None) 457 458 self.assertIsInstance(validateColor_error_, objc.selector) 459 self.assertEqual(validateColor_error_.signature, objc._C_NSBOOL + b'@:N^@o^@') 460 461 def test_Accessor(self): 462 with filterWarnings("ignore", DeprecationWarning): 463 # NOTE: the optional type argument is tested through the typedAccessor function 464 465 # Basic properties: 466 467 @objc.Accessor 468 def color(self): 469 return 42 470 471 @objc.Accessor 472 def isColor(self): 473 return 42 474 475 @objc.Accessor 476 def setColor_(self, value): 477 pass 478 479 self.assertIsInstance(color, objc.selector) 480 self.assertIsInstance(isColor, objc.selector) 481 self.assertIsInstance(setColor_, objc.selector) 482 483 self.assertEqual(color.signature, b"@@:") 484 self.assertEqual(isColor.signature, b"@@:") 485 self.assertEqual(setColor_.signature, b"v@:@") 486 487 488 # Indexed accessors 489 490 @objc.Accessor 491 def countOfFlavors(self): 492 return 2 493 494 @objc.Accessor 495 def objectInFlavorsAtIndex_(self, idx): 496 return "sour" 497 498 @objc.Accessor 499 def flavorsAtIndexes_(sef, indices): 500 return ["sour", "sweet"] 501 502 @objc.Accessor 503 def getFlavors_range_(self, buffer, range): 504 return ["sour", "sweet"] 505 506 507 self.assertIsInstance(countOfFlavors, objc.selector) 508 self.assertIsInstance(objectInFlavorsAtIndex_, objc.selector) 509 self.assertIsInstance(flavorsAtIndexes_, objc.selector) 510 self.assertIsInstance(getFlavors_range_, objc.selector) 511 512 self.assertEqual(countOfFlavors.signature, objc._C_NSUInteger + b"@:") 513 self.assertEqual(objectInFlavorsAtIndex_.signature, b"@@:" + objc._C_NSUInteger) 514 self.assertEqual(flavorsAtIndexes_.signature, b"@@:@") 515 516 # XXX: This needs even more work: also have to add custom metadata! 517 self.assertEqual(getFlavors_range_.signature, b"v@:o^@" + _C_NSRange) 518 519 # Mutable Indexed Accessors 520 521 @objc.Accessor 522 def insertObject_inFlavorsAtIndex_(self, value, idx): 523 pass 524 525 @objc.Accessor 526 def insertFlavors_atIndexes_(self, values, indices): 527 pass 528 529 @objc.Accessor 530 def removeObjectFromFlavorsAtIndex_(self, index): 531 pass 532 533 @objc.Accessor 534 def removeFlavorsAtIndexes_(self, indices): 535 pass 536 537 @objc.Accessor 538 def replaceObjectInFlavorsAtIndex_withObject_(self, value, idx): 539 pass 540 541 @objc.Accessor 542 def replaceFlavorsAtIndexes_withFlavors_(self, indices, values): 543 pass 544 545 546 self.assertIsInstance(insertObject_inFlavorsAtIndex_, objc.selector) 547 self.assertIsInstance(insertFlavors_atIndexes_, objc.selector) 548 self.assertIsInstance(removeObjectFromFlavorsAtIndex_, objc.selector) 549 self.assertIsInstance(removeFlavorsAtIndexes_, objc.selector) 550 self.assertIsInstance(replaceObjectInFlavorsAtIndex_withObject_, objc.selector) 551 self.assertIsInstance(replaceFlavorsAtIndexes_withFlavors_, objc.selector) 552 553 self.assertEqual(insertObject_inFlavorsAtIndex_.signature, b"v@:@" + objc._C_NSUInteger) 554 self.assertEqual(insertFlavors_atIndexes_.signature, b"v@:@@") 555 self.assertEqual(removeObjectFromFlavorsAtIndex_.signature, b"v@:" + objc._C_NSUInteger) 556 self.assertEqual(removeFlavorsAtIndexes_.signature, b"v@:@") 557 self.assertEqual(replaceObjectInFlavorsAtIndex_withObject_.signature, b"v@:" + objc._C_NSUInteger + b"@") 558 self.assertEqual(replaceFlavorsAtIndexes_withFlavors_.signature, b"v@:@@") 559 560 561 # Getter Unordered Accessors 562 @objc.Accessor 563 def countOfLanguages(self): 564 pass 565 566 @objc.Accessor 567 def enumeratorOfLanguages(self): 568 pass 569 570 @objc.Accessor 571 def memberOfLanguages_(self, value): 572 return False 573 574 self.assertIsInstance(countOfLanguages, objc.selector) 575 self.assertIsInstance(enumeratorOfLanguages, objc.selector) 576 self.assertIsInstance(memberOfLanguages_, objc.selector) 577 578 self.assertEqual(countOfLanguages.signature, objc._C_NSUInteger + b"@:") 579 self.assertEqual(enumeratorOfLanguages.signature, b"@@:") 580 self.assertEqual(memberOfLanguages_.signature, objc._C_NSBOOL + b"@:@") 581 582 # Mutable Unordered Accessors 583 584 @objc.Accessor 585 def addLanguagesObject_(self, value): 586 pass 587 588 @objc.Accessor 589 def addLanguagues_(self, values): 590 pass 591 592 @objc.Accessor 593 def intersectLanguagues_(self, values): 594 pass 595 596 self.assertIsInstance(addLanguagesObject_, objc.selector) 597 self.assertIsInstance(addLanguagues_, objc.selector) 598 self.assertIsInstance(intersectLanguagues_, objc.selector) 599 600 self.assertEqual(addLanguagesObject_.signature, b"v@:@") 601 self.assertEqual(addLanguagues_.signature, b"v@:@") 602 self.assertEqual(intersectLanguagues_.signature, b"v@:@") 603 604 # Validation 605 @objc.Accessor 606 def validateColor_error_(self, value, error): 607 return (False, None) 608 609 self.assertIsInstance(validateColor_error_, objc.selector) 610 self.assertEqual(validateColor_error_.signature, objc._C_NSBOOL + b'@:N^@o^@') 611 612 613 614 # Keyword arguments (**kwds) and varargs (*args) are 615 # not supported: 616 617 def attrib(self, *args): 618 pass 619 self.assertRaises(TypeError, objc.Accessor, attrib) 620 621 def attrib(self, **kwds): 622 pass 623 self.assertRaises(TypeError, objc.Accessor, attrib) 624 625 # Not really an accessor 626 def attrib_error_(self, a, b): 627 pass 628 self.assertRaises(TypeError, objc.Accessor, attrib_error_) 629 630 # Argument counts that don't match 631 def validateObject_error_(self, a): 632 pass 633 self.assertRaises(TypeError, objc.Accessor, validateObject_error_) 634 635 def validateObject_error_(self, a, b, c): 636 pass 637 self.assertRaises(TypeError, objc.Accessor, validateObject_error_) 638 639 def validateObject_error_(self, a, b, c, d=1, e=2): 640 pass 641 self.assertRaises(TypeError, objc.Accessor, validateObject_error_) 642 643 @objc.Accessor 644 def validateObject_error_(self, a, b, c=1): 645 pass 646 647 def test_signature(self): 648 649 @objc.signature(b"d@:ii") 650 def myMethod_arg_(self, a, b): 651 pass 652 653 self.assertIsInstance(myMethod_arg_, objc.selector) 654 self.assertEqual(myMethod_arg_.signature, b'd@:ii') 655 self.assertEqual(myMethod_arg_.selector, b'myMethod:arg:') 656 657 @objc.signature(b'q@:@q', selector=b'foo:bar:') 658 def method(self, a, b): 659 pass 660 661 self.assertIsInstance(method, objc.selector) 662 self.assertEqual(method.signature, b'q@:@q') 663 self.assertEqual(method.selector, b'foo:bar:') 664 665 666 667 668 669 670 671if __name__ == "__main__": 672 main() 673