1from PyObjCTools.TestSupport import * 2import objc 3import warnings 4import platform 5import sys 6 7# Most useful systems will at least have 'NSObject'. 8NSObject = objc.lookUpClass('NSObject') 9 10 11# XXX : This is a really dumb way to detect < 10.3 12if not NSObject.instancesRespondToSelector_('setValue:forKey:'): 13 # Defining protocols in an MH_BUNDLE makes < 10.3 explode 14 OC_TestProtocol = None 15else: 16 from PyObjCTest.protocol import OC_TestProtocol 17 18 19MyProto3 = objc.informal_protocol("MyProto3", ( 20 objc.selector(None, selector=b"testMethod", signature=b"I@:", isRequired=1), 21 objc.selector(None, selector=b"testMethod2:", signature=b"v@:i", isRequired=0) 22)) 23 24class Test3InformalProtocols(TestCase): 25 def testOptional(self): 26 class ProtoClass3 (NSObject, protocols=[MyProto3]): 27 def testMethod(self): 28 pass 29 30 31 32 33if (sys.maxsize < 2 ** 32) or (platform.mac_ver()[0] >= '10.7'): 34 EmptyProtocol3 = objc.formal_protocol("EmptyProtocol3", None, ()) 35 36 37 MyProtocol3 = objc.formal_protocol("MyProtocol3", None, ( 38 objc.selector(None, selector=b"protoMethod", signature=b"I@:"), 39 objc.selector(None, selector=b"anotherProto:with:", signature=b"v@:ii"), 40 )) 41 42 MyOtherProtocol3 = objc.formal_protocol("MyOtherProtocol3", 43 (MyProtocol3,), [ 44 objc.selector(None, selector=b"yetAnother:", signature=b"i@:I") 45 ]) 46 47 MyClassProtocol3 = objc.formal_protocol("MyClassProtocol3", None, [ 48 objc.selector(None, selector=b"anAnotherOne:", signature=b"i@:i"), 49 objc.selector(None, selector=b"aClassOne:", signature=b"@@:i", isClassMethod=1), 50 ]) 51 52 if OC_TestProtocol is not None: 53 54 class TestFormalOCProtocols(TestCase): 55 56 def testImplementFormalProtocol(self): 57 58 class MyClassNotImplementingProtocol(NSObject): 59 pass 60 61 self.assertFalse(MyClassNotImplementingProtocol.pyobjc_classMethods.conformsToProtocol_(OC_TestProtocol)) 62 63 try: 64 class MyClassNotAlsoImplementingProtocol(NSObject, protocols=[OC_TestProtocol]): 65 def method1(self): pass 66 67 self.fail("class not implementing protocol, yet created") 68 except TypeError: 69 pass 70 71 class MyClassImplementingProtocol(NSObject, protocols=[OC_TestProtocol]): 72 def method1(self): pass 73 def method2_(self, a): pass 74 75 self.assertTrue(MyClassImplementingProtocol.pyobjc_classMethods.conformsToProtocol_(OC_TestProtocol)) 76 77 78 79 # The PyObjC implementation of formal protocols is slightly looser 80 # than Objective-C itself: you can inherit part of the protocol 81 # from the superclass. 82 # XXX: not really: you won't inherit the right signatures by default 83 84 class MyClassImplementingHalfOfProtocol(NSObject): 85 def method1(self): pass 86 method1 = objc.selector(method1, signature=b'i@:') 87 88 self.assertFalse(MyClassImplementingHalfOfProtocol.pyobjc_classMethods.conformsToProtocol_(OC_TestProtocol)) 89 90 class MyClassImplementingAllOfProtocol(MyClassImplementingHalfOfProtocol, protocols=[OC_TestProtocol]): 91 def method2_(self, v): pass 92 93 self.assertTrue(MyClassImplementingAllOfProtocol.pyobjc_classMethods.conformsToProtocol_(OC_TestProtocol)) 94 95 96 97 98 class TestFormalProtocols (TestCase): 99 # Implement unittests for formal protocols here. 100 # 101 102 def testImplementAnotherObject(self): 103 anObject = NSObject.alloc().init() 104 105 try: 106 class MyClassImplementingAnotherObject(NSObject, protocols=[anObject]): 107 pass 108 self.fail("Can create class that implements an object???") 109 except TypeError: 110 pass 111 112 try: 113 class MyClassImplementingAnotherObject(NSObject, protocols=[10]): 114 pass 115 self.fail() 116 except TypeError: 117 pass 118 119 try: 120 class MyClassImplementingAnotherObject(NSObject, protocols=[int]): 121 pass 122 self.fail() 123 except TypeError: 124 pass 125 126 127 128 def testIncorrectlyDefiningFormalProtocols(self): 129 # Some bad calls to objc.formal_protocol 130 self.assertRaises(TypeError, objc.formal_protocol, [], None, ()) 131 self.assertRaises(TypeError, objc.formal_protocol, 'supers', (NSObject,) , ()) 132 self.assertRaises(TypeError, objc.formal_protocol, 'supers', objc.protocolNamed('NSLocking') , ()) 133 self.assertRaises(TypeError, objc.formal_protocol, 'supers', [ 134 objc.protocolNamed('NSLocking'), 135 "hello", 136 ], ()) 137 self.assertRaises(TypeError, objc.formal_protocol, 'supers', None, [ 138 objc.selector(None, selector=b'fooMethod:', signature=b'v@:i'), 139 "hello", 140 ]) 141 142 def testMethodInfo(self): 143 self.assertEqual(MyProtocol3.instanceMethods(), [ 144 {'typestr': b'I@:', 'required': True, 'selector': b'protoMethod'}, 145 {'typestr': b'v@:ii', 'required': True, 'selector': b'anotherProto:with:'}, 146 ]) 147 self.assertEqual(MyProtocol3.classMethods(), [ 148 ]) 149 self.assertEqual( 150 MyProtocol3.descriptionForInstanceMethod_(b"protoMethod"), 151 (b"protoMethod", b"I@:")) 152 153 self.assertEqual( 154 MyProtocol3.descriptionForInstanceMethod_(b"nosuchmethod"), 155 None) 156 157 self.assertEqual(MyClassProtocol3.classMethods(), [ 158 {'required': True, 'selector': b'aClassOne:', 'typestr': b'@@:i'} 159 ]) 160 self.assertEqual(MyProtocol3.classMethods(), [ 161 ]) 162 self.assertEqual( 163 MyClassProtocol3.descriptionForClassMethod_(b"aClassOne:"), 164 (b"aClassOne:", b"@@:i")) 165 166 self.assertEqual( 167 MyClassProtocol3.descriptionForClassMethod_(b"nosuchmethod"), 168 None) 169 170 171if __name__ == '__main__': 172 main() 173