summaryrefslogtreecommitdiff
path: root/Lib/ctypes/test/test_parameters.py
blob: 82704d5f3a98fa9c56966182b659b5a76605a1ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import unittest, sys

class SimpleTypesTestCase(unittest.TestCase):

    def setUp(self):
        import ctypes
        try:
            from _ctypes import set_conversion_mode
        except ImportError:
            pass
        else:
            self.prev_conv_mode = set_conversion_mode("ascii", "strict")

    def tearDown(self):
        try:
            from _ctypes import set_conversion_mode
        except ImportError:
            pass
        else:
            set_conversion_mode(*self.prev_conv_mode)


    def test_subclasses(self):
        from ctypes import c_void_p, c_char_p
        # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
        class CVOIDP(c_void_p):
            def from_param(cls, value):
                return value * 2
            from_param = classmethod(from_param)

        class CCHARP(c_char_p):
            def from_param(cls, value):
                return value * 4
            from_param = classmethod(from_param)

        self.assertEqual(CVOIDP.from_param("abc"), "abcabc")
        self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc")

        try:
            from ctypes import c_wchar_p
        except ImportError:
            return

        class CWCHARP(c_wchar_p):
            def from_param(cls, value):
                return value * 3
            from_param = classmethod(from_param)

        self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc")

    # XXX Replace by c_char_p tests
    def test_cstrings(self):
        from ctypes import c_char_p, byref

        # c_char_p.from_param on a Python String packs the string
        # into a cparam object
        s = "123"
        self.assertTrue(c_char_p.from_param(s)._obj is s)

        # new in 0.9.1: convert (encode) unicode to ascii
        self.assertEqual(c_char_p.from_param(u"123")._obj, "123")
        self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")

        self.assertRaises(TypeError, c_char_p.from_param, 42)

        # calling c_char_p.from_param with a c_char_p instance
        # returns the argument itself:
        a = c_char_p("123")
        self.assertTrue(c_char_p.from_param(a) is a)

    def test_cw_strings(self):
        from ctypes import byref
        try:
            from ctypes import c_wchar_p
        except ImportError:
##            print "(No c_wchar_p)"
            return
        s = u"123"
        if sys.platform == "win32":
            self.assertTrue(c_wchar_p.from_param(s)._obj is s)
            self.assertRaises(TypeError, c_wchar_p.from_param, 42)

            # new in 0.9.1: convert (decode) ascii to unicode
            self.assertEqual(c_wchar_p.from_param("123")._obj, u"123")
        self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")

        pa = c_wchar_p.from_param(c_wchar_p(u"123"))
        self.assertEqual(type(pa), c_wchar_p)

    def test_int_pointers(self):
        from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
        LPINT = POINTER(c_int)

##        p = pointer(c_int(42))
##        x = LPINT.from_param(p)
        x = LPINT.from_param(pointer(c_int(42)))
        self.assertEqual(x.contents.value, 42)
        self.assertEqual(LPINT(c_int(42)).contents.value, 42)

        self.assertEqual(LPINT.from_param(None), None)

        if c_int != c_long:
            self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
        self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
        self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))

    def test_byref_pointer(self):
        # The from_param class method of POINTER(typ) classes accepts what is
        # returned by byref(obj), it type(obj) == typ
        from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
        LPINT = POINTER(c_int)

        LPINT.from_param(byref(c_int(42)))

        self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
        if c_int != c_long:
            self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
        self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))

    def test_byref_pointerpointer(self):
        # See above
        from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref

        LPLPINT = POINTER(POINTER(c_int))
        LPLPINT.from_param(byref(pointer(c_int(42))))

        self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
        if c_int != c_long:
            self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
        self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))

    def test_array_pointers(self):
        from ctypes import c_short, c_uint, c_int, c_long, POINTER
        INTARRAY = c_int * 3
        ia = INTARRAY()
        self.assertEqual(len(ia), 3)
        self.assertEqual([ia[i] for i in range(3)], [0, 0, 0])

        # Pointers are only compatible with arrays containing items of
        # the same type!
        LPINT = POINTER(c_int)
        LPINT.from_param((c_int*3)())
        self.assertRaises(TypeError, LPINT.from_param, c_short*3)
        self.assertRaises(TypeError, LPINT.from_param, c_long*3)
        self.assertRaises(TypeError, LPINT.from_param, c_uint*3)

##    def test_performance(self):
##        check_perf()

    def test_noctypes_argtype(self):
        import _ctypes_test
        from ctypes import CDLL, c_void_p, ArgumentError

        func = CDLL(_ctypes_test.__file__)._testfunc_p_p
        func.restype = c_void_p
        # TypeError: has no from_param method
        self.assertRaises(TypeError, setattr, func, "argtypes", (object,))

        class Adapter(object):
            def from_param(cls, obj):
                return None

        func.argtypes = (Adapter(),)
        self.assertEqual(func(None), None)
        self.assertEqual(func(object()), None)

        class Adapter(object):
            def from_param(cls, obj):
                return obj

        func.argtypes = (Adapter(),)
        # don't know how to convert parameter 1
        self.assertRaises(ArgumentError, func, object())
        self.assertEqual(func(c_void_p(42)), 42)

        class Adapter(object):
            def from_param(cls, obj):
                raise ValueError(obj)

        func.argtypes = (Adapter(),)
        # ArgumentError: argument 1: ValueError: 99
        self.assertRaises(ArgumentError, func, 99)


################################################################

if __name__ == '__main__':
    unittest.main()