/Lib/ctypes/test/test_pep3118.py

http://unladen-swallow.googlecode.com/ · Python · 211 lines · 128 code · 39 blank · 44 comment · 15 complexity · ed44c97ec50a050d80fe3ae64d43f7d8 MD5 · raw file

  1. import unittest
  2. from ctypes import *
  3. import re, struct, sys
  4. if sys.byteorder == "little":
  5. THIS_ENDIAN = "<"
  6. OTHER_ENDIAN = ">"
  7. else:
  8. THIS_ENDIAN = ">"
  9. OTHER_ENDIAN = "<"
  10. class memoryview(object):
  11. # This class creates a memoryview - like object from data returned
  12. # by the private _ctypes._buffer_info() function, just enough for
  13. # these tests.
  14. #
  15. # It can be removed when the py3k memoryview object is backported.
  16. def __init__(self, ob):
  17. from _ctypes import _buffer_info
  18. self.format, self.ndim, self.shape = _buffer_info(ob)
  19. if self.shape == ():
  20. self.shape = None
  21. self.itemsize = sizeof(ob)
  22. else:
  23. size = sizeof(ob)
  24. for dim in self.shape:
  25. size /= dim
  26. self.itemsize = size
  27. self.strides = None
  28. self.readonly = False
  29. self.size = sizeof(ob)
  30. def normalize(format):
  31. # Remove current endian specifier and white space from a format
  32. # string
  33. if format is None:
  34. return ""
  35. format = format.replace(OTHER_ENDIAN, THIS_ENDIAN)
  36. return re.sub(r"\s", "", format)
  37. class Test(unittest.TestCase):
  38. def test_native_types(self):
  39. for tp, fmt, shape, itemtp in native_types:
  40. ob = tp()
  41. v = memoryview(ob)
  42. try:
  43. self.failUnlessEqual(normalize(v.format), normalize(fmt))
  44. self.failUnlessEqual(v.size, sizeof(ob))
  45. self.failUnlessEqual(v.itemsize, sizeof(itemtp))
  46. self.failUnlessEqual(v.shape, shape)
  47. # ctypes object always have a non-strided memory block
  48. self.failUnlessEqual(v.strides, None)
  49. # they are always read/write
  50. self.failIf(v.readonly)
  51. if v.shape:
  52. n = 1
  53. for dim in v.shape:
  54. n = n * dim
  55. self.failUnlessEqual(v.itemsize * n, v.size)
  56. except:
  57. # so that we can see the failing type
  58. print(tp)
  59. raise
  60. def test_endian_types(self):
  61. for tp, fmt, shape, itemtp in endian_types:
  62. ob = tp()
  63. v = memoryview(ob)
  64. try:
  65. self.failUnlessEqual(v.format, fmt)
  66. self.failUnlessEqual(v.size, sizeof(ob))
  67. self.failUnlessEqual(v.itemsize, sizeof(itemtp))
  68. self.failUnlessEqual(v.shape, shape)
  69. # ctypes object always have a non-strided memory block
  70. self.failUnlessEqual(v.strides, None)
  71. # they are always read/write
  72. self.failIf(v.readonly)
  73. if v.shape:
  74. n = 1
  75. for dim in v.shape:
  76. n = n * dim
  77. self.failUnlessEqual(v.itemsize * n, v.size)
  78. except:
  79. # so that we can see the failing type
  80. print(tp)
  81. raise
  82. # define some structure classes
  83. class Point(Structure):
  84. _fields_ = [("x", c_long), ("y", c_long)]
  85. class PackedPoint(Structure):
  86. _pack_ = 2
  87. _fields_ = [("x", c_long), ("y", c_long)]
  88. class Point2(Structure):
  89. pass
  90. Point2._fields_ = [("x", c_long), ("y", c_long)]
  91. class EmptyStruct(Structure):
  92. _fields_ = []
  93. class aUnion(Union):
  94. _fields_ = [("a", c_int)]
  95. class Incomplete(Structure):
  96. pass
  97. class Complete(Structure):
  98. pass
  99. PComplete = POINTER(Complete)
  100. Complete._fields_ = [("a", c_long)]
  101. ################################################################
  102. #
  103. # This table contains format strings as they look on little endian
  104. # machines. The test replaces '<' with '>' on big endian machines.
  105. #
  106. native_types = [
  107. # type format shape calc itemsize
  108. ## simple types
  109. (c_char, "<c", None, c_char),
  110. (c_byte, "<b", None, c_byte),
  111. (c_ubyte, "<B", None, c_ubyte),
  112. (c_short, "<h", None, c_short),
  113. (c_ushort, "<H", None, c_ushort),
  114. # c_int and c_uint may be aliases to c_long
  115. #(c_int, "<i", None, c_int),
  116. #(c_uint, "<I", None, c_uint),
  117. (c_long, "<l", None, c_long),
  118. (c_ulong, "<L", None, c_ulong),
  119. # c_longlong and c_ulonglong are aliases on 64-bit platforms
  120. #(c_longlong, "<q", None, c_longlong),
  121. #(c_ulonglong, "<Q", None, c_ulonglong),
  122. (c_float, "<f", None, c_float),
  123. (c_double, "<d", None, c_double),
  124. # c_longdouble may be an alias to c_double
  125. (c_bool, "<?", None, c_bool),
  126. (py_object, "<O", None, py_object),
  127. ## pointers
  128. (POINTER(c_byte), "&<b", None, POINTER(c_byte)),
  129. (POINTER(POINTER(c_long)), "&&<l", None, POINTER(POINTER(c_long))),
  130. ## arrays and pointers
  131. (c_double * 4, "(4)<d", (4,), c_double),
  132. (c_float * 4 * 3 * 2, "(2,3,4)<f", (2,3,4), c_float),
  133. (POINTER(c_short) * 2, "(2)&<h", (2,), POINTER(c_short)),
  134. (POINTER(c_short) * 2 * 3, "(3,2)&<h", (3,2,), POINTER(c_short)),
  135. (POINTER(c_short * 2), "&(2)<h", None, POINTER(c_short)),
  136. ## structures and unions
  137. (Point, "T{<l:x:<l:y:}", None, Point),
  138. # packed structures do not implement the pep
  139. (PackedPoint, "B", None, PackedPoint),
  140. (Point2, "T{<l:x:<l:y:}", None, Point2),
  141. (EmptyStruct, "T{}", None, EmptyStruct),
  142. # the pep does't support unions
  143. (aUnion, "B", None, aUnion),
  144. ## pointer to incomplete structure
  145. (Incomplete, "B", None, Incomplete),
  146. (POINTER(Incomplete), "&B", None, POINTER(Incomplete)),
  147. # 'Complete' is a structure that starts incomplete, but is completed after the
  148. # pointer type to it has been created.
  149. (Complete, "T{<l:a:}", None, Complete),
  150. # Unfortunately the pointer format string is not fixed...
  151. (POINTER(Complete), "&B", None, POINTER(Complete)),
  152. ## other
  153. # function signatures are not implemented
  154. (CFUNCTYPE(None), "X{}", None, CFUNCTYPE(None)),
  155. ]
  156. class BEPoint(BigEndianStructure):
  157. _fields_ = [("x", c_long), ("y", c_long)]
  158. class LEPoint(LittleEndianStructure):
  159. _fields_ = [("x", c_long), ("y", c_long)]
  160. ################################################################
  161. #
  162. # This table contains format strings as they really look, on both big
  163. # and little endian machines.
  164. #
  165. endian_types = [
  166. (BEPoint, "T{>l:x:>l:y:}", None, BEPoint),
  167. (LEPoint, "T{<l:x:<l:y:}", None, LEPoint),
  168. (POINTER(BEPoint), "&T{>l:x:>l:y:}", None, POINTER(BEPoint)),
  169. (POINTER(LEPoint), "&T{<l:x:<l:y:}", None, POINTER(LEPoint)),
  170. ]
  171. if __name__ == "__main__":
  172. unittest.main()