(merge 3.2) Close #4376: ctypes now supports nested structures in a endian
different than the parent structure. Patch by Vlad Riscutia.
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 @@
     """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 @@
             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
+        # nested structures with different byteorders
 
-        class T(Structure):
-            _fields_ = [("a", c_int),
-                        ("b", c_int)]
-        class S(base):
-            pass
-        self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
+        # 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.
diff --git a/Misc/ACKS b/Misc/ACKS
index 5ad6ead..10bdaf6 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -784,6 +784,7 @@
 Armin Rigo
 Nicholas Riley
 Jean-Claude Rimbault
+Vlad Riscutia
 Juan M. Bello Rivas
 Davide Rizzo
 Anthony Roach
diff --git a/Misc/NEWS b/Misc/NEWS
index 60d43f1..be49249 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -225,6 +225,9 @@
 Library
 -------
 
+- Issue #4376: ctypes now supports nested structures in a endian different than
+  the parent structure. Patch by Vlad Riscutia.
+
 - Raise ValueError when attempting to set the _CHUNK_SIZE attribute of a
   TextIOWrapper to a huge value, not TypeError.