summaryrefslogtreecommitdiffstats
path: root/Lib/ctypes
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-07-13 19:45:16 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-07-13 19:45:16 (GMT)
commitd93da2b952959c26d3afb0a66bff08ed0f14ffb9 (patch)
tree547659232e9a4f823e9e08a9c474982db081aeca /Lib/ctypes
parent90ce72dd0684e55234b969f405826af7d810e5b0 (diff)
parent6636121950a08de9d437cc2d76ac272cdceb7ecc (diff)
downloadcpython-d93da2b952959c26d3afb0a66bff08ed0f14ffb9.zip
cpython-d93da2b952959c26d3afb0a66bff08ed0f14ffb9.tar.gz
cpython-d93da2b952959c26d3afb0a66bff08ed0f14ffb9.tar.bz2
(merge 3.2) Close #4376: ctypes now supports nested structures in a endian
different than the parent structure. Patch by Vlad Riscutia.
Diffstat (limited to 'Lib/ctypes')
-rw-r--r--Lib/ctypes/_endian.py16
-rw-r--r--Lib/ctypes/test/test_byteswap.py38
2 files changed, 36 insertions, 18 deletions
diff --git a/Lib/ctypes/_endian.py b/Lib/ctypes/_endian.py
index b48bda5..721b0d1 100644
--- a/Lib/ctypes/_endian.py
+++ b/Lib/ctypes/_endian.py
@@ -7,14 +7,18 @@ def _other_endian(typ):
"""Return the type with the 'other' byte order. Simple types like
c_int and so on already have __ctype_be__ and __ctype_le__
attributes which contain the types, for more complicated types
- only arrays are supported.
+ arrays and structures are supported.
"""
- try:
+ # check _OTHER_ENDIAN attribute (present if typ is primitive type)
+ if hasattr(typ, _OTHER_ENDIAN):
return getattr(typ, _OTHER_ENDIAN)
- except AttributeError:
- if type(typ) == _array_type:
- return _other_endian(typ._type_) * typ._length_
- raise TypeError("This type does not support other endian: %s" % typ)
+ # if typ is array
+ if isinstance(typ, _array_type):
+ return _other_endian(typ._type_) * typ._length_
+ # if typ is structure
+ if issubclass(typ, Structure):
+ return typ
+ raise TypeError("This type does not support other endian: %s" % typ)
class _swapped_meta(type(Structure)):
def __setattr__(self, attrname, value):
diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py
index 83cb667..3366ba6 100644
--- a/Lib/ctypes/test/test_byteswap.py
+++ b/Lib/ctypes/test/test_byteswap.py
@@ -185,18 +185,32 @@ class Test(unittest.TestCase):
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
def test_struct_struct(self):
- # Nested structures with different byte order not (yet) supported
- if sys.byteorder == "little":
- base = BigEndianStructure
- else:
- base = LittleEndianStructure
-
- class T(Structure):
- _fields_ = [("a", c_int),
- ("b", c_int)]
- class S(base):
- pass
- self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
+ # nested structures with different byteorders
+
+ # create nested structures with given byteorders and set memory to data
+ def set_structures(endianness, nested_endianness, data):
+ class NestedStructure(nested_endianness):
+ _fields_ = [("x", c_uint32),
+ ("y", c_uint32)]
+
+ class TestStructure(endianness):
+ _fields_ = [("point", NestedStructure)]
+
+ self.assertEqual(len(data), sizeof(TestStructure))
+ return cast(data, POINTER(TestStructure))[0]
+
+ for nested, data in (
+ (BigEndianStructure, b'\0\0\0\1\0\0\0\2'),
+ (LittleEndianStructure, b'\1\0\0\0\2\0\0\0'),
+ ):
+ for parent in (
+ BigEndianStructure,
+ LittleEndianStructure,
+ Structure,
+ ):
+ s = set_structures(parent, nested, data)
+ self.assertEqual(s.point.x, 1)
+ self.assertEqual(s.point.y, 2)
def test_struct_fields_2(self):
# standard packing in struct uses no alignment.