1import unittest 2from ctypes.test import need_symbol 3import test.support 4 5class SimpleTypesTestCase(unittest.TestCase): 6 7 def setUp(self): 8 import ctypes 9 try: 10 from _ctypes import set_conversion_mode 11 except ImportError: 12 pass 13 else: 14 self.prev_conv_mode = set_conversion_mode("ascii", "strict") 15 16 def tearDown(self): 17 try: 18 from _ctypes import set_conversion_mode 19 except ImportError: 20 pass 21 else: 22 set_conversion_mode(*self.prev_conv_mode) 23 24 def test_subclasses(self): 25 from ctypes import c_void_p, c_char_p 26 # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new 27 class CVOIDP(c_void_p): 28 def from_param(cls, value): 29 return value * 2 30 from_param = classmethod(from_param) 31 32 class CCHARP(c_char_p): 33 def from_param(cls, value): 34 return value * 4 35 from_param = classmethod(from_param) 36 37 self.assertEqual(CVOIDP.from_param("abc"), "abcabc") 38 self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc") 39 40 @need_symbol('c_wchar_p') 41 def test_subclasses_c_wchar_p(self): 42 from ctypes import c_wchar_p 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 54 55 # c_char_p.from_param on a Python String packs the string 56 # into a cparam object 57 s = b"123" 58 self.assertIs(c_char_p.from_param(s)._obj, s) 59 60 # new in 0.9.1: convert (encode) unicode to ascii 61 self.assertEqual(c_char_p.from_param(b"123")._obj, b"123") 62 self.assertRaises(TypeError, c_char_p.from_param, "123\377") 63 self.assertRaises(TypeError, c_char_p.from_param, 42) 64 65 # calling c_char_p.from_param with a c_char_p instance 66 # returns the argument itself: 67 a = c_char_p(b"123") 68 self.assertIs(c_char_p.from_param(a), a) 69 70 @need_symbol('c_wchar_p') 71 def test_cw_strings(self): 72 from ctypes import c_wchar_p 73 74 c_wchar_p.from_param("123") 75 76 self.assertRaises(TypeError, c_wchar_p.from_param, 42) 77 self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377") 78 79 pa = c_wchar_p.from_param(c_wchar_p("123")) 80 self.assertEqual(type(pa), c_wchar_p) 81 82 def test_int_pointers(self): 83 from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer 84 LPINT = POINTER(c_int) 85 86## p = pointer(c_int(42)) 87## x = LPINT.from_param(p) 88 x = LPINT.from_param(pointer(c_int(42))) 89 self.assertEqual(x.contents.value, 42) 90 self.assertEqual(LPINT(c_int(42)).contents.value, 42) 91 92 self.assertEqual(LPINT.from_param(None), None) 93 94 if c_int != c_long: 95 self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42))) 96 self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42))) 97 self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42))) 98 99 def test_byref_pointer(self): 100 # The from_param class method of POINTER(typ) classes accepts what is 101 # returned by byref(obj), it type(obj) == typ 102 from ctypes import c_short, c_uint, c_int, c_long, POINTER, byref 103 LPINT = POINTER(c_int) 104 105 LPINT.from_param(byref(c_int(42))) 106 107 self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22))) 108 if c_int != c_long: 109 self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22))) 110 self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22))) 111 112 def test_byref_pointerpointer(self): 113 # See above 114 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref 115 116 LPLPINT = POINTER(POINTER(c_int)) 117 LPLPINT.from_param(byref(pointer(c_int(42)))) 118 119 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22)))) 120 if c_int != c_long: 121 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22)))) 122 self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22)))) 123 124 def test_array_pointers(self): 125 from ctypes import c_short, c_uint, c_int, c_long, POINTER 126 INTARRAY = c_int * 3 127 ia = INTARRAY() 128 self.assertEqual(len(ia), 3) 129 self.assertEqual([ia[i] for i in range(3)], [0, 0, 0]) 130 131 # Pointers are only compatible with arrays containing items of 132 # the same type! 133 LPINT = POINTER(c_int) 134 LPINT.from_param((c_int*3)()) 135 self.assertRaises(TypeError, LPINT.from_param, c_short*3) 136 self.assertRaises(TypeError, LPINT.from_param, c_long*3) 137 self.assertRaises(TypeError, LPINT.from_param, c_uint*3) 138 139 def test_noctypes_argtype(self): 140 import _ctypes_test 141 from ctypes import CDLL, c_void_p, ArgumentError 142 143 func = CDLL(_ctypes_test.__file__)._testfunc_p_p 144 func.restype = c_void_p 145 # TypeError: has no from_param method 146 self.assertRaises(TypeError, setattr, func, "argtypes", (object,)) 147 148 class Adapter(object): 149 def from_param(cls, obj): 150 return None 151 152 func.argtypes = (Adapter(),) 153 self.assertEqual(func(None), None) 154 self.assertEqual(func(object()), None) 155 156 class Adapter(object): 157 def from_param(cls, obj): 158 return obj 159 160 func.argtypes = (Adapter(),) 161 # don't know how to convert parameter 1 162 self.assertRaises(ArgumentError, func, object()) 163 self.assertEqual(func(c_void_p(42)), 42) 164 165 class Adapter(object): 166 def from_param(cls, obj): 167 raise ValueError(obj) 168 169 func.argtypes = (Adapter(),) 170 # ArgumentError: argument 1: ValueError: 99 171 self.assertRaises(ArgumentError, func, 99) 172 173 def test_abstract(self): 174 from ctypes import (Array, Structure, Union, _Pointer, 175 _SimpleCData, _CFuncPtr) 176 177 self.assertRaises(TypeError, Array.from_param, 42) 178 self.assertRaises(TypeError, Structure.from_param, 42) 179 self.assertRaises(TypeError, Union.from_param, 42) 180 self.assertRaises(TypeError, _CFuncPtr.from_param, 42) 181 self.assertRaises(TypeError, _Pointer.from_param, 42) 182 self.assertRaises(TypeError, _SimpleCData.from_param, 42) 183 184 @test.support.cpython_only 185 def test_issue31311(self): 186 # __setstate__ should neither raise a SystemError nor crash in case 187 # of a bad __dict__. 188 from ctypes import Structure 189 190 class BadStruct(Structure): 191 @property 192 def __dict__(self): 193 pass 194 with self.assertRaises(TypeError): 195 BadStruct().__setstate__({}, b'foo') 196 197 class WorseStruct(Structure): 198 @property 199 def __dict__(self): 200 1/0 201 with self.assertRaises(ZeroDivisionError): 202 WorseStruct().__setstate__({}, b'foo') 203 204 def test_parameter_repr(self): 205 from ctypes import ( 206 c_bool, 207 c_char, 208 c_wchar, 209 c_byte, 210 c_ubyte, 211 c_short, 212 c_ushort, 213 c_int, 214 c_uint, 215 c_long, 216 c_ulong, 217 c_longlong, 218 c_ulonglong, 219 c_float, 220 c_double, 221 c_longdouble, 222 c_char_p, 223 c_wchar_p, 224 c_void_p, 225 ) 226 self.assertRegex(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$") 227 self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>") 228 self.assertRegex(repr(c_wchar.from_param('a')), r"^<cparam 'u' at 0x[A-Fa-f0-9]+>$") 229 self.assertEqual(repr(c_byte.from_param(98)), "<cparam 'b' (98)>") 230 self.assertEqual(repr(c_ubyte.from_param(98)), "<cparam 'B' (98)>") 231 self.assertEqual(repr(c_short.from_param(511)), "<cparam 'h' (511)>") 232 self.assertEqual(repr(c_ushort.from_param(511)), "<cparam 'H' (511)>") 233 self.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$") 234 self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$") 235 self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$") 236 self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$") 237 self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$") 238 self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^<cparam '[LIQ]' \(20000\)>$") 239 self.assertEqual(repr(c_float.from_param(1.5)), "<cparam 'f' (1.5)>") 240 self.assertEqual(repr(c_double.from_param(1.5)), "<cparam 'd' (1.5)>") 241 self.assertEqual(repr(c_double.from_param(1e300)), "<cparam 'd' (1e+300)>") 242 self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$") 243 self.assertRegex(repr(c_char_p.from_param(b'hihi')), r"^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$") 244 self.assertRegex(repr(c_wchar_p.from_param('hihi')), r"^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$") 245 self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$") 246 247################################################################ 248 249if __name__ == '__main__': 250 unittest.main() 251