1 import unittest, sys 2 3 class SimpleTypesTestCase(unittest.TestCase): 4 5 def setUp(self): 6 import ctypes 7 try: 8 from _ctypes import set_conversion_mode 9 except ImportError: 10 pass 11 else: 12 self.prev_conv_mode = set_conversion_mode("ascii", "strict") 13 14 def tearDown(self): 15 try: 16 from _ctypes import set_conversion_mode 17 except ImportError: 18 pass 19 else: 20 set_conversion_mode(*self.prev_conv_mode) 21 22 23 def test_subclasses(self): 24 from ctypes import c_void_p, c_char_p 25 # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new 26 class CVOIDP(c_void_p): 27 def from_param(cls, value): 28 return value * 2 29 from_param = classmethod(from_param) 30 31 class CCHARP(c_char_p): 32 def from_param(cls, value): 33 return value * 4 34 from_param = classmethod(from_param) 35 36 self.assertEqual(CVOIDP.from_param("abc"), "abcabc") 37 self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc") 38 39 try: 40 from ctypes import c_wchar_p 41 except ImportError: 42 return 43 44 class CWCHARP(c_wchar_p): 45 def from_param(cls, value): 46 return value * 3 47 from_param = classmethod(from_param) 48 49 self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc") 50 51 # XXX Replace by c_char_p tests 52 def test_cstrings(self): 53 from ctypes import c_char_p, byref 54 55 # c_char_p.from_param on a Python String packs the string 56 # into a cparam object 57 s = "123" 58 self.assertTrue(c_char_p.from_param(s)._obj is s) 59 60 # new in 0.9.1: convert (encode) unicode to ascii 61 self.assertEqual(c_char_p.from_param(u"123")._obj, "123") 62 self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377") 63 64 self.assertRaises(TypeError, c_char_p.from_param, 42) 65 66 # calling c_char_p.from_param with a c_char_p instance 67 # returns the argument itself: 68 a = c_char_p("123") 69 self.assertTrue(c_char_p.from_param(a) is a) 70 71 def test_cw_strings(self): 72 from ctypes import byref 73 try: 74 from ctypes import c_wchar_p 75 except ImportError: 76 ## print "(No c_wchar_p)" 77 return 78 s = u"123" 79 if sys.platform == "win32": 80 self.assertTrue(c_wchar_p.from_param(s)._obj is s) 81 self.assertRaises(TypeError, c_wchar_p.from_param, 42) 82 83 # new in 0.9.1: convert (decode) ascii to unicode 84 self.assertEqual(c_wchar_p.from_param("123")._obj, u"123") 85 self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377") 86 87 pa = c_wchar_p.from_param(c_wchar_p(u"123")) 88 self.assertEqual(type(pa), c_wchar_p) 89 90 def test_int_pointers(self): 91 from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer 92 LPINT = POINTER(c_int) 93 94 ## p = pointer(c_int(42)) 95 ## x = LPINT.from_param(p) 96 x = LPINT.from_param(pointer(c_int(42))) 97 self.assertEqual(x.contents.value, 42) 98 self.assertEqual(LPINT(c_int(42)).contents.value, 42) 99 100 self.assertEqual(LPINT.from_param(None), None) 101 102 if c_int != c_long: 103 self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42))) 104 self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42))) 105 self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42))) 106 107 def test_byref_pointer(self): 108 # The from_param class method of POINTER(typ) classes accepts what is 109 # returned by byref(obj), it type(obj) == typ 110 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref 111 LPINT = POINTER(c_int) 112 113 LPINT.from_param(byref(c_int(42))) 114 115 self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22))) 116 if c_int != c_long: 117 self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22))) 118 self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22))) 119 120 def test_byref_pointerpointer(self): 121 # See above 122 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref 123 124 LPLPINT = POINTER(POINTER(c_int)) 125 LPLPINT.from_param(byref(pointer(c_int(42)))) 126 127 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22)))) 128 if c_int != c_long: 129 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22)))) 130 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22)))) 131 132 def test_array_pointers(self): 133 from ctypes import c_short, c_uint, c_int, c_long, POINTER 134 INTARRAY = c_int * 3 135 ia = INTARRAY() 136 self.assertEqual(len(ia), 3) 137 self.assertEqual([ia[i] for i in range(3)], [0, 0, 0]) 138 139 # Pointers are only compatible with arrays containing items of 140 # the same type! 141 LPINT = POINTER(c_int) 142 LPINT.from_param((c_int*3)()) 143 self.assertRaises(TypeError, LPINT.from_param, c_short*3) 144 self.assertRaises(TypeError, LPINT.from_param, c_long*3) 145 self.assertRaises(TypeError, LPINT.from_param, c_uint*3) 146 147 ## def test_performance(self): 148 ## check_perf() 149 150 def test_noctypes_argtype(self): 151 import _ctypes_test 152 from ctypes import CDLL, c_void_p, ArgumentError 153 154 func = CDLL(_ctypes_test.__file__)._testfunc_p_p 155 func.restype = c_void_p 156 # TypeError: has no from_param method 157 self.assertRaises(TypeError, setattr, func, "argtypes", (object,)) 158 159 class Adapter(object): 160 def from_param(cls, obj): 161 return None 162 163 func.argtypes = (Adapter(),) 164 self.assertEqual(func(None), None) 165 self.assertEqual(func(object()), None) 166 167 class Adapter(object): 168 def from_param(cls, obj): 169 return obj 170 171 func.argtypes = (Adapter(),) 172 # don't know how to convert parameter 1 173 self.assertRaises(ArgumentError, func, object()) 174 self.assertEqual(func(c_void_p(42)), 42) 175 176 class Adapter(object): 177 def from_param(cls, obj): 178 raise ValueError(obj) 179 180 func.argtypes = (Adapter(),) 181 # ArgumentError: argument 1: ValueError: 99 182 self.assertRaises(ArgumentError, func, 99) 183 184 185 ################################################################ 186 187 if __name__ == '__main__': 188 unittest.main() 189