11import unittest
22from ctypes import *
33import re , sys
4+ from _ctypes_test import buffer_info
45
56if sys .byteorder == "little" :
67 THIS_ENDIAN = "<"
@@ -20,7 +21,7 @@ def normalize(format):
2021class Test (unittest .TestCase ):
2122
2223 def test_native_types (self ):
23- for tp , fmt , shape , itemtp in native_types :
24+ for tp , fmt , shape , stride , itemtp in native_types :
2425 ob = tp ()
2526 v = memoryview (ob )
2627 try :
@@ -31,10 +32,7 @@ def test_native_types(self):
3132 self .assertEqual (len (v ) * sizeof (itemtp ), sizeof (ob ))
3233 self .assertEqual (v .itemsize , sizeof (itemtp ))
3334 self .assertEqual (v .shape , shape )
34- # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides
35- # if requested. memoryview currently reconstructs missing
36- # stride information, so this assert will fail.
37- # self.assertEqual(v.strides, ())
35+ self .assertEqual (v .strides , stride )
3836
3937 # they are always read/write
4038 self .assertFalse (v .readonly )
@@ -49,6 +47,23 @@ def test_native_types(self):
4947 print (tp )
5048 raise
5149
50+ def test_native_types_shape_strides (self ):
51+ # check that ctypes (not memoryview) correctly fills out shape and strides in buffer protocol
52+ for tp , fmt , shape , stride , itemtp in native_types :
53+ ob = tp ()
54+ v = buffer_info (ob )
55+ try :
56+ if v ['ndim' ] == 0 :
57+ self .assertEqual (v ['shape' ], None )
58+ self .assertEqual (v ['strides' ], None )
59+ else :
60+ self .assertEqual (v ['shape' ], shape )
61+ self .assertEqual (v ['strides' ], stride )
62+ except :
63+ # so that we can see the failing type
64+ print (tp )
65+ raise
66+
5267 def test_endian_types (self ):
5368 for tp , fmt , shape , itemtp in endian_types :
5469 ob = tp ()
@@ -61,8 +76,7 @@ def test_endian_types(self):
6176 self .assertEqual (len (v ) * sizeof (itemtp ), sizeof (ob ))
6277 self .assertEqual (v .itemsize , sizeof (itemtp ))
6378 self .assertEqual (v .shape , shape )
64- # XXX Issue #12851
65- # self.assertEqual(v.strides, ())
79+ self .assertEqual (v .strides , ())
6680
6781 # they are always read/write
6882 self .assertFalse (v .readonly )
@@ -141,73 +155,73 @@ class Complete(Structure):
141155
142156
143157native_types = [
144- # type format shape calc itemsize
158+ # type format shape stride calc itemsize
145159
146160 ## simple types
147161
148- (c_char , "<c" , (), c_char ),
149- (c_byte , "<b" , (), c_byte ),
150- (c_ubyte , "<B" , (), c_ubyte ),
151- (c_short , "<" + s_short , (), c_short ),
152- (c_ushort , "<" + s_ushort , (), c_ushort ),
162+ (c_char , "<c" , (), (), c_char ),
163+ (c_byte , "<b" , (), (), c_byte ),
164+ (c_ubyte , "<B" , (), (), c_ubyte ),
165+ (c_short , "<" + s_short , (), (), c_short ),
166+ (c_ushort , "<" + s_ushort , (), (), c_ushort ),
153167
154- (c_int , "<" + s_int , (), c_int ),
155- (c_uint , "<" + s_uint , (), c_uint ),
168+ (c_int , "<" + s_int , (), (), c_int ),
169+ (c_uint , "<" + s_uint , (), (), c_uint ),
156170
157- (c_long , "<" + s_long , (), c_long ),
158- (c_ulong , "<" + s_ulong , (), c_ulong ),
171+ (c_long , "<" + s_long , (), (), c_long ),
172+ (c_ulong , "<" + s_ulong , (), (), c_ulong ),
159173
160- (c_longlong , "<" + s_longlong , (), c_longlong ),
161- (c_ulonglong , "<" + s_ulonglong , (), c_ulonglong ),
174+ (c_longlong , "<" + s_longlong , (), (), c_longlong ),
175+ (c_ulonglong , "<" + s_ulonglong , (), (), c_ulonglong ),
162176
163- (c_float , "<f" , (), c_float ),
164- (c_double , "<d" , (), c_double ),
177+ (c_float , "<f" , (), (), c_float ),
178+ (c_double , "<d" , (), (), c_double ),
165179
166- (c_longdouble , "<" + s_longdouble , (), c_longdouble ),
180+ (c_longdouble , "<" + s_longdouble , (), (), c_longdouble ),
167181
168- (c_bool , "<" + s_bool , (), c_bool ),
169- (py_object , "<O" , (), py_object ),
182+ (c_bool , "<" + s_bool , (), (), c_bool ),
183+ (py_object , "<O" , (), (), py_object ),
170184
171185 ## pointers
172186
173- (POINTER (c_byte ), "&<b" , (), POINTER (c_byte )),
174- (POINTER (POINTER (c_long )), "&&<" + s_long , (), POINTER (POINTER (c_long ))),
187+ (POINTER (c_byte ), "&<b" , (), (), POINTER (c_byte )),
188+ (POINTER (POINTER (c_long )), "&&<" + s_long , (), (), POINTER (POINTER (c_long ))),
175189
176190 ## arrays and pointers
177191
178- (c_double * 4 , "<d" , (4 ,), c_double ),
179- (c_float * 4 * 3 * 2 , "<f" , (2 ,3 ,4 ), c_float ),
180- (POINTER (c_short ) * 2 , "&<" + s_short , (2 ,), POINTER (c_short )),
181- (POINTER (c_short ) * 2 * 3 , "&<" + s_short , (3 ,2 ,), POINTER (c_short )),
182- (POINTER (c_short * 2 ), "&(2)<" + s_short , (), POINTER (c_short )),
192+ (c_double * 4 , "<d" , (4 ,), ( sizeof ( c_double ),), c_double ),
193+ (c_float * 4 * 3 * 2 , "<f" , (2 ,3 ,4 ), ( 3 * 4 * sizeof ( c_float ), 4 * sizeof ( c_float ), sizeof ( c_float )), c_float ),
194+ (POINTER (c_short ) * 2 , "&<" + s_short , (2 ,), ( sizeof ( POINTER ( c_short )),), POINTER (c_short )),
195+ (POINTER (c_short ) * 2 * 3 , "&<" + s_short , (3 ,2 ,), ( 2 * sizeof ( POINTER ( c_short ),), sizeof ( POINTER ( c_short ))), POINTER (c_short )),
196+ (POINTER (c_short * 2 ), "&(2)<" + s_short , (), (), POINTER (c_short )),
183197
184198 ## structures and unions
185199
186- (Point , "T{<l:x:<l:y:}" .replace ('l' , s_long ), (), Point ),
200+ (Point , "T{<l:x:<l:y:}" .replace ('l' , s_long ), (), (), Point ),
187201 # packed structures do not implement the pep
188- (PackedPoint , "B" , (), PackedPoint ),
189- (Point2 , "T{<l:x:<l:y:}" .replace ('l' , s_long ), (), Point2 ),
190- (EmptyStruct , "T{}" , (), EmptyStruct ),
202+ (PackedPoint , "B" , (), (), PackedPoint ),
203+ (Point2 , "T{<l:x:<l:y:}" .replace ('l' , s_long ), (), (), Point2 ),
204+ (EmptyStruct , "T{}" , (), (), EmptyStruct ),
191205 # the pep doesn't support unions
192- (aUnion , "B" , (), aUnion ),
206+ (aUnion , "B" , (), (), aUnion ),
193207 # structure with sub-arrays
194- (StructWithArrays , "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}" .replace ('l' , s_long ), (), StructWithArrays ),
195- (StructWithArrays * 3 , "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}" .replace ('l' , s_long ), (3 ,), StructWithArrays ),
208+ (StructWithArrays , "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}" .replace ('l' , s_long ), (), (), StructWithArrays ),
209+ (StructWithArrays * 3 , "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}" .replace ('l' , s_long ), (3 ,), ( sizeof ( StructWithArrays ),), StructWithArrays ),
196210
197211 ## pointer to incomplete structure
198- (Incomplete , "B" , (), Incomplete ),
199- (POINTER (Incomplete ), "&B" , (), POINTER (Incomplete )),
212+ (Incomplete , "B" , (), (), Incomplete ),
213+ (POINTER (Incomplete ), "&B" , (), (), POINTER (Incomplete )),
200214
201215 # 'Complete' is a structure that starts incomplete, but is completed after the
202216 # pointer type to it has been created.
203- (Complete , "T{<l:a:}" .replace ('l' , s_long ), (), Complete ),
217+ (Complete , "T{<l:a:}" .replace ('l' , s_long ), (), (), Complete ),
204218 # Unfortunately the pointer format string is not fixed...
205- (POINTER (Complete ), "&B" , (), POINTER (Complete )),
219+ (POINTER (Complete ), "&B" , (), (), POINTER (Complete )),
206220
207221 ## other
208222
209223 # function signatures are not implemented
210- (CFUNCTYPE (None ), "X{}" , (), CFUNCTYPE (None )),
224+ (CFUNCTYPE (None ), "X{}" , (), (), CFUNCTYPE (None )),
211225
212226 ]
213227
0 commit comments