1from PyObjCTools.TestSupport import * 2import objc 3 4from Foundation import * 5import Foundation 6from PyObjCTest.testhelper import PyObjC_TestClass4 7 8try: 9 memoryview 10except NameError: 11 memoryview = None 12 13class TestNSCoderUsage(TestCase): 14 def testUsage(self): 15 class CoderClass1 (NSObject): 16 def encodeWithCoder_(self, coder): 17 # NSObject does not implement NSCoding, no need to 18 # call superclass implementation: 19 # super(CoderClass1, self).encodeWithCoder_(coder) 20 coder.encodeValueOfObjCType_at_(objc._C_INT, 2) 21 coder.encodeValueOfObjCType_at_(objc._C_DBL, 2.0) 22 coder.encodeArrayOfObjCType_count_at_(objc._C_DBL, 4, (1.0, 2.0, 3.0, 4.0)) 23 coder.encodeBytes_length_(b"hello world!", 5) 24 25 def initWithCoder_(self, coder): 26 # NSObject does not implement NSCoding, no need to 27 # call superclass implementation: 28 # self = super(CodeClass1, self).initWithCoder_(coder) 29 self = self.init() 30 self.intVal = coder.decodeValueOfObjCType_at_(objc._C_INT, None) 31 self.dblVal = coder.decodeValueOfObjCType_at_(objc._C_DBL, None) 32 self.dblArray = coder.decodeArrayOfObjCType_count_at_(objc._C_DBL, 4, None) 33 self.decodedBytes = coder.decodeBytesWithReturnedLength_(None) 34 return self 35 36 origObj = CoderClass1.alloc().init() 37 data = NSMutableData.data() 38 archiver = NSArchiver.alloc().initForWritingWithMutableData_(data) 39 archiver.encodeObject_(origObj) 40 41 archiver = NSUnarchiver.alloc().initForReadingWithData_(data) 42 newObj = archiver.decodeObject() 43 44 self.assertEqual(newObj.intVal, 2) 45 self.assertAlmostEqual(newObj.dblVal, 2.0) 46 self.assertEqual(len(newObj.dblArray), 4) 47 self.assertAlmostEqual(newObj.dblArray[0], 1.0) 48 self.assertAlmostEqual(newObj.dblArray[1], 2.0) 49 self.assertAlmostEqual(newObj.dblArray[2], 3.0) 50 self.assertAlmostEqual(newObj.dblArray[3], 4.0) 51 self.assertEqual(newObj.decodedBytes[0], b"hello") 52 self.assertEqual(newObj.decodedBytes[1], 5) 53 54 55class MyCoder (NSCoder): 56 def init(self): 57 self = super(MyCoder, self).init() 58 if self is None: return None 59 self.coded = [] 60 return self 61 62 def encodeValueOfObjCType_at_(self, tp, value): 63 self.coded.append( ("value", tp, value) ) 64 65 def encodeArrayOfObjCType_count_at_(self, tp, cnt, value): 66 self.coded.append( ("array", tp, cnt, value) ) 67 68 def encodeBytes_length_(self, bytes, length): 69 self.coded.append( ("bytes", bytes, length) ) 70 71 def decodeValueOfObjCType_at_(self, tp): 72 if tp == b'i': 73 return 42 74 elif tp == b'd': 75 return 1.5 76 77 def decodeArrayOfObjCType_count_at_(self, tp, cnt): 78 return range(cnt) 79 80 def decodeBytesWithReturnedLength_(self): 81 return (b"ABCDEabcde", 10) 82 83class TestPythonCoder(TestCase): 84 # 85 # This test accesses a NSCoder implemented in Python from Objective-C 86 # 87 # The tests only use those methods that require a custom IMP-stub. 88 # 89 def testEncoding(self): 90 coder = MyCoder.alloc().init() 91 o = PyObjC_TestClass4.alloc().init() 92 o.encodeWithCoder_(coder) 93 self.assertEqual(coder.coded, 94 [ 95 ("value", b"d", 1.5), 96 ("array", b"i", 4, (3,4,5,6)), 97 ("bytes", b"hello world", 11), 98 ]) 99 100 def testDecoding(self): 101 coder = MyCoder.alloc().init() 102 o = PyObjC_TestClass4 103 104 self.assertEqual(o.fetchInt_(coder), 42) 105 self.assertEqual(o.fetchDouble_(coder), 1.5) 106 107 d = o.fetchData_(coder) 108 self.assertEqual(d.length(), 10) 109 110 b = d.bytes() 111 if isinstance(b, memoryview): 112 self.assertEqual(b.tobytes(), b"ABCDEabcde") 113 else: 114 self.assertEqual(bytes(b), b"ABCDEabcde") 115 116 d = o.fetchArray_(coder) 117 self.assertEqual(tuple(range(10)), tuple(d)) 118 119 def testMethods(self): 120 self.assertResultIsBOOL(NSCoder.allowsKeyedCoding) 121 self.assertArgIsBOOL(NSCoder.encodeBool_forKey_, 0) 122 self.assertResultIsBOOL(NSCoder.containsValueForKey_) 123 self.assertResultIsBOOL(NSCoder.decodeBoolForKey_) 124 125 self.assertResultHasType(NSCoder.decodeBytesForKey_returnedLength_, b'^v') 126 self.assertResultSizeInArg(NSCoder.decodeBytesForKey_returnedLength_, 1) 127 self.assertArgIsOut(NSCoder.decodeBytesForKey_returnedLength_, 1) 128 129 self.assertTrue(hasattr(Foundation, 'NXReadNSObjectFromCoder')) 130 131 @min_os_level('10.8') 132 def testMethods10_8(self): 133 self.assertResultIsBOOL(NSCoder.requiresSecureCoding) 134 135if __name__ == '__main__': 136 main( ) 137